java.io.WriteAbortedException:写入中止;java.io.NotSerializableException [英] java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException
问题描述
Tomcat 出现这种错误的原因是什么?
What causes this kind of error in 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)
推荐答案
只需实现Serializable
如果您收到 NotSerializableException
如下,
java.io.NotSerializableException: bean.ProjectAreaBean
那么它只是意味着由异常消息中的完全限定名称标识的类(在您的情况下为 bean.ProjectAreaBean
)没有实现 Serializable
接口,而它是代码所期望的在后面.修复比较简单,让类实现Serializable
接口即可.
then it simply means that the class as identified by the fully qualified name in the exception message (which is bean.ProjectAreaBean
in your case) does not implement the Serializable
interface while it is been expected by the code behind. Fixing it is relatively simple, just let the class implement the Serializable
interface.
package bean;
import java.io.Serializable;
public class ProjectAreaBean implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}
serialVersionUID
字段不是必需的,但强烈建议这样做,因为它保持了类的不同版本及其实例的序列化表示之间的二进制兼容性.因此,当您稍后向类中添加新的可序列化字段时,您需要更改 serialVersionUID
字段(通常只需将其增加 1 就足够了)以防止在反序列化实例的过程中出现问题类的旧版本.Eclipse 等 IDE 还提供了一个选项来(重新)生成 serialVersionUID
值,该值基本上是基于所有字段计算的哈希值.
The serialVersionUID
field is not necessary, but strongly recommended as this maintains the binary compatibility between different versions of the class and the serialized representations of its instances. So when you add later a new serializable field to the class, then you'd need to change the serialVersionUID
field (usually just incrementing it by 1 is sufficient) to prevent problems during deserialization of an instance of an older version of the class. IDEs like Eclipse also offer an option to (re)generate the serialVersionUID
value which is basically a hash computed based on all fields.
- JSF 托管 bean 导致 java.io.Tomcat 部署期间的 NotSerializableException
- 注入不可序列化的应用程序范围bean 作为集群中可序列化会话作用域 bean 的托管属性
- 什么是serialVersionUID,为什么要使用
如果您的 Serializable
类又包含一个字段/属性,该字段/属性引用了另一个绝对不能成为 Serializable
的类的实例(通常,这些代表资源,例如InputStream
、Connection
等),那么您需要将其标记为 transient
.这样它就会在类的序列化过程中被跳过.
If your Serializable
class contains in turn a field/property referencing an instance of another class which can absolutely not be made Serializable
(usually, these represent resources, such as InputStream
, Connection
, etc), then you'd need to mark it transient
. This way it will be skipped during serialization of the class.
private transient SomeObject thisWillNotBeSerialized;
您需要了解,反序列化后,该字段将始终变为 null
.请注意,在反序列化期间不调用类的构造函数和初始化块.如果您想对序列化和反序列化进行更细粒度的控制,请覆盖 readObject()
和 writeObject()
方法.您可以在以下链接中找到具体示例:
You need to understand that after deserialization this field would always become null
. Note that the class' constructor and initialization blocks are not invoked during deserialization. If you'd like to have finer grained control over serialization and deserialization, then override the readObject()
and writeObject()
methods. You can find concrete examples in below links:
至于为什么您需要担心序列化,这是因为大多数 Java servlet 容器(如 Tomcat)需要在存储这些类的实例时实现 Serializable
作为 HttpSession
的一个属性.这是因为 HttpSession
可能需要保存在本地磁盘文件系统上,甚至当 servlet 容器需要关闭/重启或被放置在会话已进行同步.
As to the why you need to worry about serialization, this is because most Java servlet containers like Tomcat require classes to implement Serializable
whenever instances of those classes are been stored as an attribute of the HttpSession
. That is because the HttpSession
may need to be saved on the local disk file system or even transferred over network when the servlet container needs to shutdown/restart or is being placed in a cluster of servers wherein the session has to be synchronized.
为了能够将 Java 对象保存在本地磁盘文件系统上或通过网络传输它们,必须首先将它们转换为字节流(基本上:byte[]
或InputStream
) 并且只有在对象背后的类实现了 Serializable
时才有可能.Serializable
接口本身并没有做任何事情,它只是一个标记界面.后面的代码只是对会话属性进行 instanceof Serializable
检查以采取相应的行动.
In order to be able to save Java objects on the local disk file system or transfer them over network, they have to be converted to a byte stream first (basically: a byte[]
or an InputStream
) and that is only possible if the class behind the object implements Serializable
. The Serializable
interface itself doesn't really do anything, it's merely a marker interface. The code behind merely does an instanceof Serializable
check on the session attribute to act accordingly.
java.io.Serializable
javadoc- Java Object Serialization Specification
- Java Tutorials - Essential Classes - Basic I/O - Object Streams
这篇关于java.io.WriteAbortedException:写入中止;java.io.NotSerializableException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!