java.io.WriteAbortedException:写入中止;java.io.NotSerializableException [英] java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException

查看:45
本文介绍了java.io.WriteAbortedException:写入中止;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.

如果您的 Serializable 类又包含一个字段/属性,该字段/属性引用了另一个绝对不能成为 Serializable 的类的实例(通常,这些代表资源,例如InputStreamConnection 等),那么您需要将其标记为 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆