Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dubbo GenericInvoke throws exception local class incompatible #4675

Closed
2 tasks
qixiaobo opened this issue Jul 26, 2019 · 9 comments · Fixed by #5800
Closed
2 tasks

dubbo GenericInvoke throws exception local class incompatible #4675

qixiaobo opened this issue Jul 26, 2019 · 9 comments · Fixed by #5800
Assignees
Milestone

Comments

@qixiaobo
Copy link
Contributor

  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate.

Environment

  • Dubbo version: dubbo2.7.x GenericInvoke dubbo2.5.x
  • Operating System version: all
  • Java version: 1.8/1.7

java serialization

Steps to reproduce this issue

Too simple , we can make any exception

In this code

   if (result.hasException()
                        && !(result.getException() instanceof GenericException)) {
                    return new RpcResult(new GenericException(result.getException()));
                }

We wrap all exceptions to GenericException.
But dubbo 2.7.x rename package to apache, so to make a new class like

@Deprecated
public class GenericException extends org.apache.dubbo.rpc.service.GenericException {

    public GenericException() {
    }

    public GenericException(String exceptionClass, String exceptionMessage) {
        super(exceptionClass, exceptionMessage);
    }

    public GenericException(Throwable cause) {
        super(cause);
    }
}

No serialVersionUID is provided!

Pls. provide [GitHub address] to reproduce this issue.

Expected Result

GenericException can be handled by consumer!

Actual Result

What actually happens?

If there is an exception, please attach the exception trace:

Caused by: java.util.concurrent.ExecutionException: org.apache.dubbo.remoting.RemotingException: java.io.InvalidClassException: com.alibaba.dubbo.rpc.service.GenericException; local class incompatible: stream classdesc serialVersionUID = -1182299763306599962, local class serialVersionUID = -9195665492488780691
java.io.InvalidClassException: com.alibaba.dubbo.rpc.service.GenericException; local class incompatible: stream classdesc serialVersionUID = -1182299763306599962, local class serialVersionUID = -9195665492488780691
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
        at org.apache.dubbo.common.serialize.java.JavaObjectInput.readObject(JavaObjectInput.java:75)
        at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.handleException(DecodeableRpcResult.java:144)
        at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:86)
        at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:112)
        at org.apache.dubbo.rpc.protocol.dubbo.DubboCodec.decodeBody(DubboCodec.java:92)
        at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:122)
        at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:82)
        at org.apache.dubbo.rpc.protocol.dubbo.DubboCountCodec.decode(DubboCountCodec.java:48)
        at org.apache.dubbo.remoting.transport.netty4.NettyCodecAdapter$InternalDecoder.decode(NettyCodecAdapter.java:90)
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:617)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:534)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.lang.Thread.run(Thread.java:748)
@qixiaobo
Copy link
Contributor Author

qixiaobo commented Jul 26, 2019

Why java ? ? ?
Because in 2.5.3 dubbo hessian serialization has bug ……

@qixiaobo
Copy link
Contributor Author

qixiaobo commented Jul 26, 2019

We should know this make java serialization incompatible

Deleting fields – If a field is deleted in a class, the stream written will not contain its value. When the stream is read by an earlier class, the value of the field will be set to the default value because no value is available in the stream. However, this default value may adversely impair the ability of the earlier version to fulfill its contract.
Moving classes up or down the hierarchy – This cannot be allowed since the data in the stream appears in the wrong sequence.
Changing a non-static field to static or a non-transient field to transient – When relying on default serialization, this change is equivalent to deleting a field from the class. This version of the class will not write that data to the stream, so it will not be available to be read by earlier versions of the class. As when deleting a field, the field of the earlier version will be initialized to the default value, which can cause the class to fail in unexpected ways.
Changing the declared type of a primitive field – Each version of the class writes the data with its declared type. Earlier versions of the class attempting to read the field will fail because the type of the data in the stream does not match the type of the field.
Changing the writeObject or readObject method so that it no longer writes or reads the default field data or changing it so that it attempts to write it or read it when the previous version did not. The default field data must consistently either appear or not appear in the stream.
Changing a class from Serializable to Externalizable or vice-versa is an incompatible change since the stream will contain data that is incompatible with the implementation of the available class.
Changing a class from a non-enum type to an enum type or vice versa since the stream will contain data that is incompatible with the implementation of the available class.
Removing either Serializable or Externalizable is an incompatible change since when written it will no longer supply the fields needed by older versions of the class.
Adding the writeReplace or readResolve method to a class is incompatible if the behavior would produce an object that is incompatible with any older version of the class.

@qixiaobo
Copy link
Contributor Author

So we must make the old GenericException back……

@beiwei30
Copy link
Member

would you mind to provide a pull request for this issue? @qixiaobo

@beiwei30 beiwei30 added this to the 2.7.5 milestone Jul 30, 2019
@qixiaobo
Copy link
Contributor Author

would you mind to provide a pull request for this issue? @qixiaobo

You can see #4676

@qixiaobo
Copy link
Contributor Author

qixiaobo commented Aug 9, 2019

We need this fixed, it effects our generic invoke while throwing exception

@qixiaobo
Copy link
Contributor Author

qixiaobo commented Aug 9, 2019

For me, I think RpcException also has this problem.

@qixiaobo
Copy link
Contributor Author

qixiaobo commented Aug 9, 2019

 throw new RpcException(
                                new StringBuilder(32).append("Generic serialization [")
                                    .append(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
                                    .append("] only support message type ")
                                    .append(byte[].class)
                                    .append(" and your message type is ")
                                    .append(args[i].getClass()).toString());
                        }

@b2fc
Copy link

b2fc commented Jun 30, 2020

@chickenlj 你好, #5800 GenericFilter为了兼容2.6.x及以下版本,GenericException换成了alibaba包的类,但这样2.7.x以上的版本处理GenericFilter的GenericException,都要更换为alibaba包的类吗,而这个类是@deprecated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants