当从一个VM到另一个VM进行轮询RMI调用时,我遇到了一些零星的异常。VM之间的类路径看起来是一致的。我使用的是64位java -jres是一致的**(jdk/v1.6.0_23- 64 bit)。虚拟机之间的-XX:+UseCompressedOops flag & -XX:+UseConcMarkSweepGC
存在不一致性,但我不知道这是否是根本原因?
调用(客户端)VM设置了-XX:+UseCompressedOops & -XX:+UseConcMarkSweepGC
,调用getStatistics()的服务器VM没有设置。
需要注意的几点:
1.在遇到异常之后,相同VM之间的后续调用在一段时间内是正常的-即Invalid ClassException是暂时性问题。
1.[class]和[fieldname]在每次遇到异常时都会发生变化,其中异常为java.io.InvalidClassException:[class];字段[fieldname]的不兼容类型
从-XX:+UseCompressedOops
的64位**虚拟机到另一个未设置为使用压缩oops的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
谢谢你的帮助
5条答案
按热度按时间hof1towb1#
这个选项(-XX:+UseCompressedOops)是否默认为您使用的VM启用,如果没有,我建议禁用它并尝试它。
可能是您正在使用的JRE更新中的一个错误,您可以在Oracle论坛中讨论它。
rks48beu2#
首先请注意,自6 u23发布以来,-XX:+UseCompressedOops默认设置为打开,即使您没有显式禁用它。
此外,这个选项只影响指向RAM内存的指针的内部表示,而不会在序列化对象中进行编码,因此它一定不会影响RMI调用。
我敢打赌,这个问题与内存中动态创建的一些字节码有关,由于某种原因,当第一次反序列化时,这些字节码还不可用。这可能是像Hibernate和其他使用新的自定义字节码 Package 原始类的库的情况。
46scxncf3#
只是为了确定,两个VM中的类共享相同的类编译版本?你可以尝试重新编译并添加相同的jar到两个虚拟机。
我希望这已经得到了照顾。
uyto3xhc4#
嗯,有没有可能在连接调试器的情况下重现这种情况?在ObjectStreamClass中的
throw
处有一个断点,在此抛出异常:当抛出异常时,您至少可以检查
getTypeCode
返回值。不是一个解决方案,我知道,但可能会给予一些线索/更多的细节,以包括在可能的错误报告。mgdq6dx15#
最有可能的情况是同一个类有两个不同的编译版本。但有时候很坚韧追查。检查以下内容: