Java ObjectInputStream中有两种类似的方法:
和
文档说明:
public Object readUnshared() throws IOException, ClassNotFoundException
从ObjectInputStream中读取“非共享”对象。此方法与readObject相同,不同之处在于它阻止对readObject和readUnshared的后续调用返回对通过此调用获得的反序列化实例的其他引用。具体做法是:
如果调用readUnshared反序列化反向引用(先前已写入流的对象的流表示),则抛出ObjectStreamException。
如果readUnshared成功返回,则后续尝试反序列化对readUnshared反序列化的流句柄的反向引用将导致抛出ObjectStreamException。
通过readUnshared反序列化对象使与返回的对象关联的流句柄无效。请注意,这本身并不总能保证readUnshared返回的引用是唯一的;反序列化对象可以定义readResolve方法,该方法返回对其他方可见的对象,或者readUnshared可以返回可在流中的其他位置或通过外部方式获得的Class对象或枚举常量。如果反序列化对象定义了readResolve方法,并且该方法的调用返回一个数组,那么readUnshared将返回该数组的浅层克隆;这保证了返回的数组对象是唯一的,并且无法在ObjectInputStream上调用readObject或readUnshared时再次获取,即使已经操作了基础数据流。
覆盖此方法的ObjectInputStream子类只能在拥有“enableSubclassImplementation”SerializablePermission的安全上下文中构造;没有此权限实例化此类子类的任何尝试都将导致抛出SecurityException。
但我想知道是否有人使用.readUnshared()
vs .readObject()
答案 0 :(得分:0)
我认为这可能是与安全相关的非常特殊的案例(?)。喜欢这个(来自here)。
A.6保护非共享反序列化对象
如果某个类具有任何私有或包私有对象引用字段, 并且该类依赖于这些对象引用不是的事实 在类(或包)之外可用,然后引用 必须将对象作为反序列化的一部分进行防御性复制 进程,或者ObjectOutputStream.writeUnshared和 ObjectInputStream.readUnshared方法(在1.4版本中引入) 应该使用JavaTM 2 SDK,标准版来确保唯一性 对内部对象的引用。
在复制方法中,从流中反序列化子对象 应被视为"不受信任的输入":新创建的对象, 初始化为与反序列化的子对象具有相同的值, 应该通过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(); }
在考虑序列化时,这个问题尤为重要 包含内部(必然是私有)引用的不可变对象 可变子对象。如果没有采取特殊措施来复制子对象 在反序列化容器对象期间,然后是恶意方 对序列化流的写访问可能违反容器对象 通过伪造对其可变子对象的引用并使用它们来实现不变性 引用更改容器对象的内部状态。因此,在此 例如,不可变容器类必须提供一个 特定于类的反序列化方法,它使私有副本 它反序列化的每个可变组件对象。请注意 保持不变性的目的,没有必要复制 不可变组件对象。
同样重要的是要注意,调用克隆可能并不总是如此 正确的方法来防御性地复制子对象。如果克隆方法不能 被指望产生一个独立的副本(而不是&#34;窃取&#34; a 参考副本),应使用替代手段来制作 副本。如果是,应始终使用另一种复制方法 由于克隆方法或帮助器,子对象的类不是最终的 它调用的方法可以被子类覆盖。
从JavaTM 2 SDK的标准版1.4版开始,是唯一的 通过使用,也可以确保对反序列化对象的引用 ObjectOutputStream.writeUnshared和ObjectInputStream.readUnshared 方法,从而避免了复杂性,性能成本和内存 防御性复制的开销。