在Tomcat中导致此类错误的原因是什么?
SEVERE: Exception loading sessions from persistent storage
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException:
bean.ProjectAreaBean
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1333)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(
DelegatingMethodAccessorImpl.java:25)
答案 0 :(得分:44)
Serializable
如果你得到一个NotSerializableException
如下,
java.io.NotSerializableException: bean.ProjectAreaBean
然后它只是意味着由异常消息中的完全限定名称(在您的情况下为bean.ProjectAreaBean
)标识的类没有实现Serializable
接口,而它是由预期的代码背后。修复它相对简单,只需让类实现Serializable
接口。
package bean;
import java.io.Serializable;
public class ProjectAreaBean implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}
serialVersionUID
字段不是必需的,但强烈建议这样做,因为这样可以维护类的不同版本与其实例的序列化表示之间的二进制兼容性。因此,当您稍后向类中添加新的可序列化字段时,您需要更改serialVersionUID
字段(通常只需将其递增1就足够了)以防止在旧版本的实例的反序列化过程中出现问题班级。像Eclipse这样的IDE还提供了(重新)生成serialVersionUID
值的选项,该值基本上是基于所有字段计算的哈希值。
transient
如果你的Serializable
类依次包含一个引用另一个类的实例的字段/属性,那么绝对不能Serializable
(通常,这些代表资源,例如InputStream
, Connection
等),然后您需要将其标记为transient
。这样,在类的序列化过程中将跳过它。
private transient SomeObject thisWillNotBeSerialized;
您需要了解,在反序列化后,此字段将始终为null
。请注意,在反序列化期间,类的构造函数和初始化块是而不是。如果您希望对序列化和反序列化进行更精细的控制,请覆盖readObject()
和writeObject()
方法。您可以在以下链接中找到具体示例:
至于为什么你需要担心序列化,这是因为大多数Java servlet容器如Tomcat都要求类在这些类的实例存储为属性时实现Serializable
的HttpSession
。这是因为当servlet容器需要关闭/重启或者被放置在必须同步会话的服务器集群中时,HttpSession
可能需要保存在本地磁盘文件系统上,甚至可以通过网络传输。
为了能够在本地磁盘文件系统上保存Java对象或通过网络传输它们,必须先将它们转换为字节流(基本上是:byte[]
或InputStream
)并且只有在对象后面的类实现Serializable
时才可能。 Serializable
接口本身并没有真正做任何事情,它只是一个marker interface。后面的代码仅对会话属性进行instanceof Serializable
检查以相应地执行操作。
答案 1 :(得分:3)
您需要bean.ProjectAreaBean
可序列化。