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

查找违规的不可序列化成员变量的路径

谢鸿羲
2023-03-14
问题内容

在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。一切都很好,除了Exception并不能为您提供快速解决问题所需的全部功能。它会告诉您哪些类无法序列化。您的堆栈跟踪可能看起来像这样:

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具有一个称为的成员对象引用nonSerializableReference,该对象引用已设置为的一个实例ClassIDidntExplicitlyReference,而不是Serializable。我希望看到类似以下内容的内容:

my.package.MyClass.nonSerializableReference instanceof some.package.and.ClassIDidntExplicitlyReference

我知道这个问题可能没有快速解决方案,可能会涉及使用Reflections。有人在这里做过吗?如果是这样,您愿意分享您的见解吗?

回答

我最终使用了反射FieldModifier类来查找路径。不幸的是,我无法共享我的代码(违反公司政策),但可以向您展示我的输出。类A持有B的一个实例,B持有C的一个实例,C持有D的一个实例。Serializable除了D之外,所有其他。我最终使用Depth-
First-Search来查找路径:

A.b -> 
  B.c -> 
    C.d instanceof class D

如果我进行了C.d瞬态搜索,则搜索不会产生任何结果。太酷了!


问题答案:

这是一个奇怪的问题-您想在运行时确定在编译时应执行的操作。从理论上讲,路径的对象 不应该 事-你需要找到一个参考的东西都是不可序列来修复你的代码的对象。

也就是说,您可以使用反射编写一个简单的递归树搜寻器。就是说,您可能可以实现自己的ObjectInputStream来记录适当进入的对象。我建议看一下来源以获取更多详细信息



 类似资料:
  • 如果类B扩展了类A,则类B实现可序列化,而类A有一个不可序列化的公共非静态初始化变量。。。尝试使用FileOutputStream的writeObject()方法写入类“B”对象时,将序列化从a继承的不可序列化成员,以便将其与类B的其余变量一起写入文件,还是将引发NotSerializableException?我试过了,效果不错,但我不知道为什么。。。所以我不确定它是否总是有效,或者我错过了什么

  •   - a - addr : rt_i2c_bus_device , rt_i2c_msg ai_addr : addrinfo ai_addrlen : addrinfo ai_canonname : addrinfo ai_family : addrinfo ai_flags : addrinfo ai_next : addrinfo ai_protocol : addrinfo ai_soc

  • 主要内容:使用“键值对”初始化结构体,使用多个值的列表初始化结构体,初始化匿名结构体结构体在实例化时可以直接对成员变量进行初始化,初始化有两种形式分别是以字段“键值对”形式和多个值的列表形式,键值对形式的初始化适合选择性填充字段较多的结构体,多个值的列表形式适合填充字段较少的结构体。 使用“键值对”初始化结构体 结构体可以使用“键值对”(Key value pair)初始化字段,每个“键”(Key)对应结构体中的一个字段,键的“值”(Value)对应字段需要初始化的值。 键值对的

  • 这里列出了所有文档化的结构体和联合体的成员变量,并附带结构或联合所属的文件: - a - addr : rt_i2c_bus_device , rt_i2c_msg ai_addr : addrinfo ai_addrlen : addrinfo ai_canonname : addrinfo ai_family : addrinfo ai_flags : addrinfo ai_next : a

  •   - y - y : rt_device_rect_info

  •   - x - x : rt_device_rect_info xfer : rt_spi_ops