使用Caucho Hessian v3/v4升级Java

eh57zj3b  于 2023-09-29  发布在  Java
关注(0)|答案(1)|浏览(126)

bounty还有6天到期。回答此问题可获得+150声望奖励。MatWein希望引起更多的注意这个问题。
问题:

我们目前正在使用Caucho Hessian 3.2.0与Java 8和Java 11应用程序结合使用。这工作正常,但我们想迁移到Java 17,我们得到以下systen.out消息:

java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String java.lang.StackTraceElement.classLoaderName accessible: module java.base does not "opens java.lang" to unnamed module @78e03bb5
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
    at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)
    at com.caucho.hessian.io.JavaDeserializer.getFieldMap(JavaDeserializer.java:299)
    at com.caucho.hessian.io.JavaDeserializer.<init>(JavaDeserializer.java:77)
    at com.caucho.hessian.io.StackTraceElementDeserializer.<init>(StackTraceElementDeserializer.java:60)
    at com.caucho.hessian.io.SerializerFactory.<clinit>(SerializerFactory.java:627)
    at com.caucho.hessian.io.AbstractHessianOutput.findSerializerFactory(AbstractHessianOutput.java:95)
    at com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:486)
    at Main.serializeWithHessian(Main.java:23)
    at Main.main(Main.java:13)

有一种解决方法,即添加以下JVM参数:

--add-opens java.base/java.lang=ALL-UNNAMED

我们不想在所有生产应用程序中使用此标志,因此我们尝试将Hessian升级到最新版本4.0.66。基本上,这适用于最常见的用例,但当我们多次序列化具有相同对象示例的数据时,这不起作用。
我创建了一个小的示例应用程序:https://github.com/MatWein/hessian-test
这个应用程序从它的类路径中读取一些Java序列化的测试数据,并尝试用Hessian序列化和反序列化它。如果您使用Hessian 3.2.0运行此应用程序,则它适用于运行和调试模式下的所有Java版本(8,11和17,如果您设置了上面的JVM标志)。但我不能让它与Hessian 4.0.66工作,因为以下错误发生:

Exception in thread "main" com.caucho.hessian.io.HessianFieldException: de.test.TestData.field29: de.test.PaymentType cannot be assigned from null
    at com.caucho.hessian.io.FieldDeserializer2FactoryUnsafe.logDeserializeError(FieldDeserializer2FactoryUnsafe.java:538)
    at com.caucho.hessian.io.FieldDeserializer2FactoryUnsafe$ObjectFieldDeserializer.deserialize(FieldDeserializer2FactoryUnsafe.java:169)
    at com.caucho.hessian.io.UnsafeDeserializer.readObject(UnsafeDeserializer.java:237)
    at com.caucho.hessian.io.UnsafeDeserializer.readObject(UnsafeDeserializer.java:148)
    at com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2202)
    at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2123)
    at com.caucho.hessian.io.CollectionDeserializer.readLengthList(CollectionDeserializer.java:93)
    at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2050)
    at Main.deserializeWithHessian(Main.java:32)
    at Main.main(Main.java:15)
Caused by: java.lang.IndexOutOfBoundsException: Index 13 out of bounds for length 13
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
    at java.base/java.util.Objects.checkIndex(Objects.java:361)
    at java.base/java.util.ArrayList.get(ArrayList.java:427)
    at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1810)
    at com.caucho.hessian.io.FieldDeserializer2FactoryUnsafe$ObjectFieldDeserializer.deserialize(FieldDeserializer2FactoryUnsafe.java:165)
    ... 8 more

注意:我们在运行和调试应用程序之间有不同的运行时行为(不知道为什么,但Hessian似乎使用了Unsafe类,Weak&Soft引用等)。
对我来说,这看起来像是黑森州的内部bug。它在序列化站点上使用类com.caucho.hessian.util.IdentityIntMap,但是在序列化时客户端找不到对象引用索引。

**问题:**有没有办法让Hessian 4.0.66与Java 8、11和17(或至少与Java 11和17)一起工作?

wecizke3

wecizke31#

最后,经过大量的调试,发现了问题。问题是枚举字段具有null值。
在Hessian 3.x.x中,默认情况下允许对选中的Enum类型的null值进行反序列化。
但是在Hessian 4.x.x中,他们改变了计算枚举值的方法,并且不允许对检查的枚举类型的null值进行反序列化。

注:我用的是4.0.66黑森。它将与所有版本的(JDK 8,11,17)(已测试)
修复:

1.**第一个解决方案:**使用transient关键字PaymentTypeGenderTypeActivationState,因为它们带有null值,应该避免成为反序列化的一部分。

**注意:**在为Enum字段放置transient之前,请确保选择您认为不需要作为序列化一部分的字段,并且确保在反序列化发生时,这些Enum字段的数据将在那里。

public class TestData implements Serializable {
    private static final long serialVersionUID = 8316361431446795589L;

    private transient ActivationState field18;
    private transient PaymentType field29;
    private transient GenderType field34;

    ... // getters and setters
}

JDK 11输出:

/Users/anisb/Library/Java/JavaVirtualMachines/corretto-11.0.19/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=59693:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/anisb/hessian-test/target/classes:/Users/anisb/.m2/repository/com/caucho/hessian/4.0.66/hessian-4.0.66.jar Main
[de.test.TestData@12f41634, de.test.TestData@7a3d45bd, de.test.TestData@87f383f, de.test.TestData@e720b71, de.test.TestData@27f723, de.test.TestData@612fc6eb, de.test.TestData@4d3167f4, de.test.TestData@4923ab24, de.test.TestData@50d0686, de.test.TestData@1a3869f4, de.test.TestData@3aeaafa6, de.test.TestData@13c27452, de.test.TestData@1060b431, de.test.TestData@7b69c6ba, de.test.TestData@46daef40, de.test.TestData@a38d7a3, de.test.TestData@11758f2a, de.test.TestData@5ed828d, de.test.TestData@670b40af, de.test.TestData@44c8afef, de.test.TestData@262b2c86, de.test.TestData@ed9d034, de.test.TestData@612679d6, de.test.TestData@76a3e297, de.test.TestData@4eb7f003, de.test.TestData@371a67ec, de.test.TestData@63440df3, de.test.TestData@6121c9d6, de.test.TestData@77f99a05, de.test.TestData@5f3a4b84, de.test.TestData@eafc191]

Process finished with exit code 0

JDK 8输出:

/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=59763:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/charsets.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/cldrdata.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/dnsns.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/jaccess.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/localedata.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/nashorn.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/sunec.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/ext/zipfs.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/jce.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/jfr.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/jsse.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/management-agent.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/resources.jar:/Users/anisb/Library/Java/JavaVirtualMachines/corretto-1.8.0_362/Contents/Home/jre/lib/rt.jar:/Users/anisb/hessian-test/target/classes:/Users/anisb/.m2/repository/com/caucho/hessian/4.0.66/hessian-4.0.66.jar Main
[de.test.TestData@7fbe847c, de.test.TestData@442d9b6e, de.test.TestData@4c98385c, de.test.TestData@1c655221, de.test.TestData@1b9e1916, de.test.TestData@1edf1c96, de.test.TestData@368102c8, de.test.TestData@1963006a, de.test.TestData@4f8e5cde, de.test.TestData@5eb5c224, de.test.TestData@1b701da1, de.test.TestData@58d25a40, de.test.TestData@53e25b76, de.test.TestData@ee7d9f1, de.test.TestData@3f8f9dd6, de.test.TestData@45fe3ee3, de.test.TestData@6996db8, de.test.TestData@759ebb3d, de.test.TestData@73a8dfcc, de.test.TestData@7e774085, de.test.TestData@504bae78, de.test.TestData@ba8a1dc, de.test.TestData@ea30797, de.test.TestData@4cdf35a9, de.test.TestData@17d10166, de.test.TestData@484b61fc, de.test.TestData@726f3b58, de.test.TestData@3b764bce, de.test.TestData@aec6354, de.test.TestData@15615099, de.test.TestData@5fcfe4b2]

Process finished with exit code 0

JDK 17输出:

/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=59813:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/anisb/hessian-test/target/classes:/Users/anisb/.m2/repository/com/caucho/hessian/4.0.66/hessian-4.0.66.jar Main
[de.test.TestData@12bb4df8, de.test.TestData@11028347, de.test.TestData@39a054a5, de.test.TestData@2f333739, de.test.TestData@1f89ab83, de.test.TestData@14899482, de.test.TestData@3caeaf62, de.test.TestData@7382f612, de.test.TestData@21588809, de.test.TestData@2a33fae0, de.test.TestData@7b3300e5, de.test.TestData@71bc1ae4, de.test.TestData@6ed3ef1, de.test.TestData@77468bd9, de.test.TestData@e73f9ac, de.test.TestData@383534aa, de.test.TestData@311d617d, de.test.TestData@7b1d7fff, de.test.TestData@61064425, de.test.TestData@16f65612, de.test.TestData@6bc168e5, de.test.TestData@3b192d32, de.test.TestData@2437c6dc, de.test.TestData@2e5c649, de.test.TestData@707f7052, de.test.TestData@299a06ac, de.test.TestData@7c53a9eb, de.test.TestData@1055e4af, de.test.TestData@2aae9190, de.test.TestData@ed17bee, de.test.TestData@136432db]

Process finished with exit code 0

1.**第二种解决方案:**请确保在相应的Enum字段中发送非空值,以避免出现以下错误。

Exception in thread "main" com.caucho.hessian.io.HessianFieldException: <package>.<Class>.<field-name>: <package>.<Enum> cannot be assigned from null

相关问题