You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consumer sends List<Byte> with values like (byte) 1, (byte) 2, (byte) 127
Provider receives the parameters and checks element types
Expected behavior
Provider receives List<Byte> with elements of type java.lang.Byte.
Actual behavior
Provider receives List<Integer> — all Byte elements are deserialized as Integer. This causes ClassCastException when the provider code tries to use the elements as Byte.
Same issue affects List<Short>, List<Float>, Map<K, Byte>, Map<K, Short>, etc. — any collection/map with narrow number type arguments.
Root cause
Dubbo passes only the erased Class (e.g., List.class) to the serialization framework during request deserialization, discarding the generic Type (e.g., List<Byte>). The serialization framework (hessian2) has no way to know the element type should be Byte, so it defaults to Integer for small numbers.
Specifically:
ReflectionMethodDescriptor stores method.getParameterTypes() (raw Class[]) but not method.getGenericParameterTypes() (which includes ParameterizedType).
DecodeableRpcInvocation.drawArgs() only calls in.readObject(Class), never in.readObject(Class, Type).
ReflectionPackableMethod.WrapRequestUnpack similarly only passes Class<?>[] to MultipleSerialization.deserialize().
Hessian2ObjectInput.readObject(Class, Type) ignores the Type parameter entirely.
Tested & verified
Reproduced with Dubbo 3.3.6 (official release) on both dubbo and triple protocol
Fix verified with both dubbo and triple protocol via E2E testing
Verified with Arthas that the new code paths are executed at runtime
Environment
Steps to reproduce
List<Byte>orMap<String, Byte>parameters:List<Byte>with values like(byte) 1, (byte) 2, (byte) 127Expected behavior
Provider receives
List<Byte>with elements of typejava.lang.Byte.Actual behavior
Provider receives
List<Integer>— allByteelements are deserialized asInteger. This causesClassCastExceptionwhen the provider code tries to use the elements asByte.Same issue affects
List<Short>,List<Float>,Map<K, Byte>,Map<K, Short>, etc. — any collection/map with narrow number type arguments.Root cause
Dubbo passes only the erased
Class(e.g.,List.class) to the serialization framework during request deserialization, discarding the genericType(e.g.,List<Byte>). The serialization framework (hessian2) has no way to know the element type should beByte, so it defaults toIntegerfor small numbers.Specifically:
ReflectionMethodDescriptorstoresmethod.getParameterTypes()(rawClass[]) but notmethod.getGenericParameterTypes()(which includesParameterizedType).DecodeableRpcInvocation.drawArgs()only callsin.readObject(Class), neverin.readObject(Class, Type).ReflectionPackableMethod.WrapRequestUnpacksimilarly only passesClass<?>[]toMultipleSerialization.deserialize().Hessian2ObjectInput.readObject(Class, Type)ignores theTypeparameter entirely.Tested & verified
3.3.6(official release) on both dubbo and triple protocol