在 Java 中,序列化使读取和写入对象到流非常容易。例如,以下代码片段几乎就是将对象写入流所需的全部内容:
ObjectOutputStream oos = ... //Initialize your output stream
Object toWrite = ... //Initialize what you want to write here
oos.writeObject(toWrite); //Writes the object to the stream
oos.flush();
toWrite
如果的类实现了Serializable
接口,并且 的所有toWrite
非transient
成员变量也是,这将工作得很好Serializable
。换句话说,您尝试通过toWrite
引用发送的整个对象层次结构必须是Serializable
. 假设这段代码的唯一问题是里面toWrite
的东西不是Serializable
.
如果层次结构不完全Serializable
,则调用会oos.writeObject(toWrite)
抛出java.io.NotSerializableException
. 这一切都很好,除了异常并没有为您提供快速解决问题所需的一切。它会告诉你哪些类不能被序列化。您的堆栈跟踪可能如下所示:
java.io.NotSerializableException: some.package.and.ClassIDidntExplicitlyReference
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
...
at my.package.MyClass.codeThatWroteTheOffendingObject(MyClass.java:###)
这种类型为您指明了正确的方向,但在涉及由 引用的深层对象层次结构的情况下,toWrite
并不总是清楚有问题的类引用来自哪里。假设我分配toWrite
给 的一个实例,MyClass
并且我的实例MyClass
有一个名为的成员 Object 引用nonSerializableReference
,该引用已设置为 的实例ClassIDidntExplicitlyReference
,而不是Serializable
。我希望看到类似下面的打印出来:
my.package.MyClass.nonSerializableReference instanceof some.package.and.ClassIDidntExplicitlyReference
我知道这个问题可能没有快速解决方案,并且可能涉及使用反射。以前这里有没有人这样做过,如果是这样,你介意分享你的见解吗?
回答
我最终使用反射Field
和Modifier
类来找到路径。不幸的是,我无法分享我的代码(违反公司政策),但我可以向您展示我的输出。A 类持有 B 的实例,B 持有 C 的实例,C 持有 D 的实例。Serializable
除了 D 之外,我最终使用 Depth-First-Search 来查找路径:
A.b ->
B.c ->
C.d instanceof class D
如果我做C.d
瞬态,搜索不会产生任何结果。很酷!