Java InvalidClassException:<;类别>;;字段类型不兼容<;fieldname>;
在从一个VM向另一个VM轮询RMI调用时,我会遇到一些零星的异常。 虚拟机之间的类路径看起来是一致的。我使用的是64位java—JRE是一致的(jdk/v1.6.0_23-64位)。 虚拟机之间的Java InvalidClassException:<;类别>;;字段类型不兼容<;fieldname>;,java,serialization,64-bit,rmi,Java,Serialization,64 Bit,Rmi,在从一个VM向另一个VM轮询RMI调用时,我会遇到一些零星的异常。 虚拟机之间的类路径看起来是一致的。我使用的是64位java—JRE是一致的(jdk/v1.6.0_23-64位)。 虚拟机之间的-XX:+UseCompressedOops标志和-XX:+UseConcMarkSweepGC不一致,但我不知道这两者是否都是根本原因 调用(客户端)VM已设置-XX:+UseCompressedOops&-XX:+useConMarkSweepGC集,在其上进行getStatistics()调用的服
-XX:+UseCompressedOops标志和-XX:+UseConcMarkSweepGC
不一致,但我不知道这两者是否都是根本原因
调用(客户端)VM已设置-XX:+UseCompressedOops&-XX:+useConMarkSweepGC
集,在其上进行getStatistics()调用的服务器VM未设置
需要注意的几点:-
-XX:+UseCompressedOops
从64位虚拟机向另一个未设置为使用压缩OOP的64位虚拟机进行RMI调用(序列化)是否有问题
堆栈:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.io.InvalidClassException: testserver.cluster.Status; incompatible types for field committed
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy14.getStatistics(Unknown Source)
at testserver.rm.RM$Check.run(RM.java:1593)
Caused by: java.io.InvalidClassException: testserver.cluster.Status; incompatible types for field committed
at java.io.ObjectStreamClass.matchFields(ObjectStreamClass.java:2210)
at java.io.ObjectStreamClass.getReflector(ObjectStreamClass.java:2105)
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:602)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
... 4 more
谢谢你的帮助。有没有可能在附加调试程序的情况下重现这种情况?在引发异常的ObjectStreamClass中的
throw
处具有断点:
if ((f.isPrimitive() || lf.isPrimitive())
&& f.getTypeCode() != lf.getTypeCode()) {
throw new InvalidClassException(localDesc.name,
"incompatible types for field "
+ f.getName());
}
当抛出异常时,您至少可以检查getTypeCode
返回值。我知道这不是一个解决方案,但可能会在可能的错误报告中提供一些线索/更多详细信息。对于您正在使用的VM,默认情况下是否启用了此选项(-XX:+UseCompressedOops),如果否,我建议禁用并尝试
可能是您正在使用的JRE更新中的一个bug,您可以在Oracle论坛上讨论它。首先请注意,自6u23发布以来,-XX:+UseCompressedOops默认设置为打开,即使您没有显式禁用它 此外,此选项只影响指向RAM内存的指针的内部表示,这些指针不会在序列化对象中编码,因此它不能影响RMI调用
我敢打赌,这个问题与在内存中动态创建的某些字节码有关,由于某些原因,在第一次反序列化时这些字节码还不可用。Hibernate和其他用新的自定义字节码包装原始类的库可能就是这种情况。可以肯定的是,两个VM中的类共享相同的类编译版本吗? 您是否可以尝试重新编译并向两个VM添加相同的jar
我希望已经注意到了。您好,类路径是一致的。committed是标准类(如ArrayList)的原始类型(int)异常。。。InvalidClassException:java.util.ArrayList;字段大小的不兼容类型由于这两种类型都是
int
,因此32/64位之间当然可能存在问题。如果您在这里找不到明确的答案,您可能可以将其带到openjdk/oracle邮件列表…回复:最后一段暗示了陈旧的流程-我最初也这么认为。但是机器被弹回了,我仍然明白这个问题。如果这是一个常规的类路径问题,我希望异常是一致的,但它只出现一次,然后同一个VM之间的通信是正常的(没有重新启动它们)。您是否运行任何检测工具,如visualvm?推测:如果他们在运行两个类时使用仪器,可能会有一段时间不一样。我还不能(对Q)发表评论。