ReadResolve 必须具有 Object 返回类型,而不是 void¶
ID: java/wrong-readresolve-signature
Kind: problem
Security severity:
Severity: warning
Precision: medium
Tags:
- reliability
- maintainability
- language-features
Query suites:
- java-security-and-quality.qls
如果类使用 readResolve
方法来指定从流中读取对象时要替换的对象实例,请确保 readResolve
的签名 *完全* 与 Java 序列化机制期望的签名一致。
建议¶
确保类中 readResolve
方法的签名与预期签名一致
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
请注意,该方法 *必须* 返回 java.lang.Object
。
如果 readResolve
用于可序列化单例的实例控制(即,确保对单例类的反序列化不会导致单例的另一个实例),则可以使用具有单个元素的 enum
代替。Java 序列化规范明确确保对 enum
的反序列化不会创建新实例。(有关此技术的详细信息,请参阅 [Bloch]。)
示例¶
在以下示例中,FalseSingleton.readResolve
的签名不正确,这会导致反序列化创建单例的新实例。但是,Singleton.readResolve
具有正确的签名,这意味着反序列化不会导致单例的另一个实例。
class FalseSingleton implements Serializable {
private static final long serialVersionUID = -7480651116825504381L;
private static FalseSingleton instance;
private FalseSingleton() {}
public static FalseSingleton getInstance() {
if (instance == null) {
instance = new FalseSingleton();
}
return instance;
}
// BAD: Signature of 'readResolve' does not match the exact signature that is expected
// (that is, it does not return 'java.lang.Object').
public FalseSingleton readResolve() throws ObjectStreamException {
return FalseSingleton.getInstance();
}
}
class Singleton implements Serializable {
private static final long serialVersionUID = -7480651116825504381L;
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// GOOD: Signature of 'readResolve' matches the exact signature that is expected.
// It replaces the singleton that is read from a stream with an instance of 'Singleton',
// instead of creating a new singleton.
private Object readResolve() throws ObjectStreamException {
return Singleton.getInstance();
}
}
参考资料¶
Java API 规范: Serializable.
Java 对象序列化规范: 3.7 The readResolve 方法, 1.12 枚举常量的序列化.
J. Bloch, Effective Java (第二版), 第 77 条. Addison-Wesley, 2008.