当前位置: 首页 > 面试题库 >

readResolve无法正常工作?:Guava的SerializedForm的一个实例出现

戎志勇
2023-03-14
问题内容

在对我们的一种数据结构进行反序列化时(使用默认机制(无自定义writeObject / readObject)),显示了ImmutableMap $
SerializedForm的实例(来自Google的Guava库)。

guava的客户端不应该看到这样的实例,因为SerialreadForm的实例已使用readResolve替换(例如,参见com.google.common.collect.ImmutableMap类中的“
writeReplace”)。

因此,反序列化失败并显示以下消息:

java.lang.ClassCastException: cannot assign instance of com.google.common.collect.ImmutableMap$SerializedForm
to field .. of type java.util.Map in instance of com.blah.C

这是正确的,因为ImmutableMap $ SerializedForm不是java.util.Map的子类型,但是应该将其替换。怎么了?

我们在com.blah.C类中没有自定义的writeObject /
readObject。我们在父对象(包含com.blah.C)中确实有自定义序列化代码。

更新,这是stacktrace的顶部:

java.lang.ClassCastException: cannot assign instance of com.google.common.collect.ImmutableSet$SerializedForm to field com.blah.ast.Automaton.bodyNodes of type java.util.Set in instance of com.blah.ast.Automaton
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2039)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1212)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1952)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:479)
at com.blah.ast.AstNode.readObject(AstNode.java:189)
at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:479)
at com.blah.ast.AstNode.readObject(AstNode.java:189)

问题答案:

这周,我们再次遇到了这个错误。但我找到了根本原因。ObjectInputStream使用的类加载器是高度依赖上下文的(有人会说不 确定性
)。这是Sun文档的相关部分(摘自ObjectInputStream#resolveClass(ObjectStreamClass)):

[class loader]的确定如下:如果当前线程的堆栈上有一个方法的声明类是由用户定义的class
loader定义的(并且不是为实现反射调用而生成的),则它是class
loader对应于最接近当前执行帧的这种方法;否则为null。如果此调用导致ClassNotFoundException且传递的ObjectStreamClass实例的名称是原始类型或void的Java语言关键字,则将返回表示该原始类型或void的Class对象(例如,名称为“
int”的ObjectStreamClass
”将解析为Integer.TYPE)。否则,ClassNotFoundException将被抛出给该方法的调用者。

在我们的应用程序中,我们有一个Eclipse插件B,它依赖于仅实用程序的插件A。我们正在反序列化其类在B中的对象,但是反序列化是在A中启动的(在那里创建ObjectInputStream),这就是问题所在。反序列化很少(即取决于文档所说的调用堆栈)选择了错误的类加载器(一个不能加载B类的加载器)。为了解决此问题,我们将适当的加载程序从顶级反序列化调用程序(在B中)传递给A中的Utility方法。此方法现在使用如下的自定义ObjectInputStream(请注意,自由变量“
loader”):

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)) {
                @SuppressWarnings("rawtypes")
                @Override
                protected Class resolveClass(ObjectStreamClass objectStreamClass)
                        throws IOException, ClassNotFoundException {
                    return Class.forName(objectStreamClass.getName(), true, loader);
                }
            };


 类似资料:
  • 请帮忙 我正在尝试为我拥有的一款游戏(Android)构建APK。我试过构建和构建并运行,但都不适合我<当我使用“构建”时,我会遇到以下两个问题。第一个问题是,它说构建成功了,但没有任何构建/APK。第二个问题是,嗯,我对它知之甚少。在下面。 使用成功的UnityEngine的结果完成构建。GUI实用程序:过程事件(int32,intPtr) 虽然它说构建已经完成,结果成功了,但这是错误的。我的意

  • 问题内容: 我正在尝试通过CORS将表单数据从www.siteone.com发布到www.sitetwo.com。我的ajax代码是这样的: 并且文件cors.php 如下: 但是仍然会引发Access-control-Allow-Origin错误。引发的错误是这样的: 我知道,通过仅通过标头允许远程网站来使用CORS,就可以使用跨域请求。但是当我这样尝试时,会引发错误。我在这里错过了什么吗?这是

  • 问题内容: 我现在已经安装了Docker工具箱,并且收到所有错误: 输出: 但是VM在VirtualBox下运行。我到处搜索,但找不到解决方案。 UPDATE1 :我正在使用Windows 8.1,并且还尝试通过Kinematic进行启动。 UPDATE2:当我尝试Virtualbox Test Build 5.0.3或更高版本时,一切都像魅力一样。 您可以在这里下载:https : //www.

  • 问题内容: 我每天都使用TimedRotatingFileHandler记录Django日志并轮换使用,但是检查日志文件,奇怪的问题是昨天的日志被截断了,今天的日志很少,昨天的日志丢失了! Django 1.4 uwsgi 1.4.9 Python 2.6 我从uwsgi开始8个django实例。setting.py是 我错过了什么?为什么旧的日志丢失了? 问题答案: 您不应该同时从多个进程登录到

  • 问题内容: 因此,我的设置无法按我想要的方式工作。因此,每当我运行该程序时,它就会立即从0变为100。我尝试使用,任务,并尝试了,但没有任何尝试。 这是我的程序: @MadProgrammer这是我尝试做一名摆动工作人员并将每个名称写入文档并更新进度栏的尝试。该程序将达到86%左右并停止运行,永远不会创建完成的文档。该程序将创建一个空白文档。这是我首先创建的SwingWorker对象,这是两种方法

  • 问题内容: 我在JLayeredpane上有两个JPanels。其中一个显示pdf,重叠的一个具有透明背景(我使用过setOpaque(false))。现在,我可以将图形添加到透明面板中,这样看来我实际上是在注释pdf。我想要一个橡皮擦工具来删除这些注释。我尝试使用以下代码 其中path是由多条线构成的形状。现在,不是在先前的图形上绘制 透明线 ,而是绘制 黑线 。我要去哪里错了? 问题答案: 请