yibiner opened a new issue, #16440:
URL: https://github.com/apache/dubbo/issues/16440

   ### Pre-check
   
   - [x] I am sure that all the content I provide is in English.
   
   
   ### Search before asking
   
   - [x] I had searched in the 
[issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no 
similar issues.
   
   
   ### Apache Dubbo Component
   
   Java SDK (apache/dubbo)
   
   ### Dubbo Version
   
   Dubbo Java 3.3.6 (latest release, reproduced), also 3.3.7-SNAPSHOT (main 
branch).
   OpenJDK 21, Ubuntu 20.04
   Protocol: dubbo (hessian2) and triple (hessian2 / hessian4).
   
   ### Steps to reproduce this issue
   
   Typical production scenario: a service accepting binary chunks keyed by name.
   
   public interface UploadService {
       String uploadChunks(Map<String, List<Byte>> chunks);
   }
   
   1. Consumer sends `Map<String, List<Byte>>` whose inner lists contain
      `(byte) 1, (byte) 127, (byte) -1`.
   2. Provider reads the argument and does a strong-typed access:
      `byte first = chunk.get(0);`
   
   Reproduced on the latest release (Dubbo 3.3.6) with a real dubbo:// + 
hessian2
   provider/consumer demo. On the provider, the argument deserializes with inner
   elements widened to `Integer` instead of `Byte`:
   
       [provider] received "c1" = ArrayList, first element runtime type = 
java.lang.Integer
   
   The typed access then throws. The provider-side stack trace (dubbo frames
   included, trimmed in the middle for readability):
   
       java.lang.ClassCastException: class java.lang.Integer cannot be cast to
         class java.lang.Byte (java.lang.Integer and java.lang.Byte are in 
module
         java.base of loader 'bootstrap')
           class java.lang.Byte (java.lang.Integer and java.lang.Byte are in 
module
         java.base of loader 'bootstrap')
           at 
demo.provider.UploadServiceImpl.uploadChunks(UploadServiceImpl.java:21)
           at 
demo.provider.UploadServiceImplDubboWrap0.invokeMethod(UploadServiceImplDubboWrap0.java)
           at 
org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:89)
           at 
org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:100)
           at 
org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:55)
           ... (dubbo server filter chain, trimmed) ...
           at 
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:167)
           at 
org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:110)
           at 
org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:205)
           at 
org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
           at 
org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:64)
   
   Dubbo's own provider-side log reports it the same way (unchecked, 
undeclared):
   
       ERROR ExceptionFilter - Got unchecked and undeclared exception ... 
service:
       demo.api.UploadService, method: uploadChunks, exception:
       java.lang.ClassCastException ... error code: 5-36
   
   Typical production scenario 2 (same root cause): nested generic collections,
   e.g. `List<List<Byte>>` chunked byte streams or `Map<String, List<Float>>`
   metric values — inner elements are widened to `Integer`/`Double` the same 
way.
   
   ### What you expected to happen
   
   Provider receives `Map<String, List<Byte>>` whose inner lists contain
   `java.lang.Byte` elements, so the typed read works and no ClassCastException
   is thrown. Same for the other affected generic shapes (scenario 2).
   
   ### Anything else
   
   This is likely related to the generic-type handling addressed in 
#16197/#16198,
   but it still reproduces on the latest release 3.3.6 and on the latest 3.3 
main.
   
   Root cause: hessian2 wire format encodes Byte/Short/Integer all as int and
   Float/Double as double, so the element type can only be restored from the
   declared generic type. On RPC top-level arguments Dubbo deserializes with 
only
   the erased Class, so narrow element types are widened.
   
   Workarounds: use `byte[]` instead of `List<Byte>`; or 
`List<Long>`/`List<Double>`/
   `List<String>` which do not lose type; or switch to `fastjson2` which is
   self-describing.
   
   ### Do you have a (mini) reproduction demo?
   
   - [x] Yes, I have a minimal reproduction demo to help resolve this issue 
more effectively!
   
   ### Are you willing to submit a pull request to fix on your own?
   
   - [ ] Yes I am willing to submit a pull request on my own!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to