java 什么时候使用ObjectInputStream.readUnshared()和readObject()?

n9vozmp4  于 2022-12-25  发布在  Java
关注(0)|答案(2)|浏览(169)

Java ObjectInputStream中有两个类似的方法:
读取非共享()
以及
读取对象()
该文件规定:
第一个月
从ObjectInputStream读取“非共享”对象。此方法与readObject相同,只是它防止对readObject和readUnshared的后续调用返回对通过此调用获取的反序列化示例的其他引用。具体而言:
如果调用readUnshared以反序列化反向引用(先前已写入流的对象的流表示形式),则将引发ObjectStreamException。
如果readUnshared成功返回,则任何后续尝试反序列化对由readUnshared反序列化的流句柄的反向引用都将导致引发ObjectStreamException。
通过readUnshared反序列化一个对象会使与返回对象相关的流句柄失效。注意,这本身并不能保证readUnshared返回的引用是唯一的;反序列化的对象可定义返回对其它方可见的对象的readResolve方法,或者readUnshared可返回可在流中的其它地方或通过外部手段获得的Class对象或枚举常量。如果反序列化的对象定义readResolve方法并且对该方法的调用返回数组,则readUnshared返回该数组的浅克隆;这保证了返回的数组对象是唯一的,并且不能从ObjectInputStream上的readObject或readUnshared的调用第二次获得,即使底层数据流已经被操纵。
重写此方法的ObjectInputStream子类只能在拥有“enableSubclassImplementation”SerializablePermission的安全上下文中构造;任何试图示例化这样一个子类而没有这个许可的行为都将导致抛出SecurityException。
但我想知道是否有人在真实的生活中使用.readUnshared().readObject()

ovfsdjhp

ovfsdjhp1#

我相信这可能是与安全性有关的非常特殊的情况(?)。就像这个(来自here)。
A.6保护非共享反序列化对象
如果类具有任何私有或包私有对象引用字段,并且该类依赖于这些对象引用在该类外部不可用这一事实(或包),则必须作为反序列化过程的一部分防御性地复制引用的对象,否则必须复制ObjectOutputStream.writeUnshared和ObjectInputStream.readUnshared方法(在JavaTM 2 SDK标准版1.4版中引入),以确保对内部对象的唯一引用。
在复制方法中,从流反序列化的子对象应被视为“不可信输入”:新创建的对象(初始化为具有与反序列化的子对象相同的值)应通过readObject方法替换子对象。例如,假设某个对象具有必须保持私有的私有字节数组字段b:

private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
{
    s.defaultReadObject();

    b = (byte[])b.clone();

    if (<invariants are not satisfied>)
        throw new java.io.StreamCorruptedException();
}

在考虑序列化包含内部如果在容器对象的反串行化期间没有采取特殊措施来复制子对象,则具有对串行化流的写访问的恶意方可通过伪造对其可变子对象的引用来侵犯容器对象的不变性,并使用这些引用来改变容器对象的内部状态。因此,在这种情况下,不可变容器类必须提供类专用的反序列化方法,该方法制作它反序列化的每个可变组件对象的私有副本。注意,为了保持不可变性,不必复制不可变组件对象。
同样重要的是要注意,调用clone并不总是防御性复制子对象的正确方法。如果clone方法不能产生独立的副本(并且不“窃取”对副本的引用),则应使用替代手段来产生副本。如果子对象的类不是最终的,则应始终使用替代的复制手段,因为它调用的clone方法或helper方法可能被子类覆盖。
从JavaTM 2 SDK标准版1.4版本开始,还可以通过使用ObjectOutputStream.writeUnshared和ObjectInputStream.readUnshared方法来确保对反序列化对象的唯一引用,从而避免防御性复制的复杂性、性能成本和内存开销。

ecr0jaav

ecr0jaav2#

当readObject()产生OutOfMemory异常时,我成功使用了readUnshared()。更多信息:https://orenkishon.wordpress.com/2014/06/28/java-memory-leak-caused-by-objectinputstream/

相关问题