我的 java 项目中有数千个类。其中一些实现了可序列化接口(interface)。现在这里有一个问题。有可能有人可以进入类,添加既不是 transient 也不是可序列化的新变量。代码编译良好,但进程会在运行时崩溃。
为了说明这一点
class Foo implements Serializable { .... // all good }
class Foo implements Serializable
{
// OOps, executorService is not serializable. It's not declared as transient either
private ExecutorService executorService = ..
}
我正在考虑编写一个将遍历所有类并确保“真正的可串行化”的单元测试。我读过一些关于序列化特定对象的讨论。我理解这个过程,但它需要
1) 创建对象。
2) 序列化然后
3) 反序列化。
有没有更高效实用的方法。也许使用反射。遍历所有类,如果类具有可序列化,则所有属性必须是可序列化的或具有 transient 关键字..
想法?
最佳答案
1) creating an object. 2) serializing and then 3) deserializing.
此列表不完整;你还需要初始化。考虑这个例子:
class CanBeSerialized implements Serializable {
private String a; // serializable
private Thread t; // not serializable
}
class CannotBeSerialized implements Serializable {
private String a; // serializable
private Thread t = new Thread(); // not serializable
}
您可以序列化和反序列化第一个,但您将在第二个上得到 NotSerializableException
。更复杂的是,如果使用了接口(interface),你永远无法判断一个类是否会通过序列化,因为它是将被流式传输的接口(interface)后面的类的具体对象:
class PerhapsCanBeSerializedButYouNeverKnow implements Serializable {
private Runnable r; // interface type - who knows?
}
前提是您可以保证对您的所有类和您的类使用的类进行以下测试:
- 存在默认构造函数,
- 字段中没有接口(interface)类型,
然后你可以通过反射自动创建和初始化它们,然后测试序列化。但这是一个非常艰难的条件,不是吗?否则,正确的初始化将取决于手动工作。
您可以以不同的方式使用反射:遍历要检查的 Class
对象列表,为它们获取 Field[]
,并验证它们是否是 transient 的 (Field.getModifiers()
) 或者如果它们直接实现 Serializable
(Field.getType().getInterfaces()
) 或间接实现(通过 super 接口(interface)或类)。此外,请考虑您想要检查的深度,具体取决于您的序列化机制的工作深度。
正如 Ryan 正确指出的那样,如果代码足够邪恶,此静态序列化检查将失败:
class SeeminglySerializable implements Serializable {
// ...
private void writeObject/readObject() {
throw new NotSerializableException();
}
}
或者如果 readObject()/writeObject()
执行不当。要针对此类问题进行测试,您需要实际测试序列化过程,而不是其背后的代码。
关于java - Java项目中所有类的单元测试可序列化性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7732259/