Java InvalidClassException:<;类别>;;字段类型不兼容<;fieldname>;

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()调用的服

在从一个VM向另一个VM轮询RMI调用时,我会遇到一些零星的异常。 虚拟机之间的类路径看起来是一致的。我使用的是64位java—JRE是一致的(jdk/v1.6.0_23-64位)。 虚拟机之间的
-XX:+UseCompressedOops标志和-XX:+UseConcMarkSweepGC
不一致,但我不知道这两者是否都是根本原因

调用(客户端)VM已设置
-XX:+UseCompressedOops&-XX:+useConMarkSweepGC
集,在其上进行getStatistics()调用的服务器VM未设置

需要注意的几点:-

  • 遇到异常后,在相同的 虚拟机在一段时间内是正常的,即无效类异常 这是一个暂时的问题

  • [class]和[fieldname]在每次 在异常为的位置遇到异常 java.io.InvalidClassException:[class];不兼容的类型 字段[字段名]

  • 使用
    -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)发表评论。