apache/dubbo

[Bug] List<Byte>, List<Short>, Map<String, Byte> deserialized as List<Integer>, Map<String, Integer> on provider side

Open

#16197 opened on Apr 9, 2026

View on GitHub
 (1 comment) (0 reactions) (0 assignees)Java (41,524 stars) (26,453 forks)batch import
help wanted

Description

Environment

  • Dubbo version: 3.2.x / 3.3.x (all versions affected)
  • Protocol: dubbo (hessian2) and triple (hessian2)
  • JDK: 17

Steps to reproduce

  1. Define an RPC interface with List<Byte> or Map<String, Byte> parameters:
public interface GreetingService {
    String processByteCollection(List<Byte> byteList, Map<String, Byte> byteMap);
}
  1. Consumer sends List<Byte> with values like (byte) 1, (byte) 2, (byte) 127
  2. 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

Contributor guide