java.io.WriteAbortedException:写入中止; java.io.NotSerializedException

发布于 2024-08-22 07:30:34 字数 653 浏览 5 评论 0原文

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)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮世清欢 2024-08-29 07:30:34

如果

您遇到 NotSerializedException 如下所示,

java.io.NotSerializableException: bean.ProjectAreaBean

那么它只是表示由异常消息中的完全限定名称标识的类(即 bean.ProjectAreaBean在你的情况下)没有实现 Serialized 接口,而这是后面的代码所期望的。修复它相对简单,只需让类实现 Serialized 接口即可。

package bean;

import java.io.Serializable;

public class ProjectAreaBean implements Serializable {
    private static final long serialVersionUID = 1L;

    // ...
}

serialVersionUID 字段不是必需的,但强烈建议使用,因为这可以保持类的不同版本及其实例​​的序列化表示之间的二进制兼容性。因此,当您稍后向类中添加新的可序列化字段时,您需要更改 serialVersionUID 字段(通常只需将其增加 1 就足够了),以防止在反序列化实例的过程中出现问题。该类的旧版本。像 Eclipse 这样的 IDE 还提供了一个选项来(重新)生成 serialVersionUID 值,该值基本上是基于所有字段计算的哈希值。

另请参阅:


标记不可序列化字段transient

如果你的Serialized类又包含一个引用另一个类的实例的字段/属性绝对不能可序列化(通常,这些表示资源,例如InputStreamConnectionUploadedFile 等),那么您需要将其标记为transient。这样,它将在类的序列化过程中被跳过。

private transient SomeObject thisWillNotBeSerialized;

您需要了解,反序列化后该字段将始终变为 null。请注意,反序列化期间不会调用类的构造函数和初始化块。如果您希望对序列化和反序列化进行更细粒度的控制,请重写 readObject()writeObject() 方法。您可以在此答案中找到具体示例: 如何在 Android 中使用 DefaultHttpClient 制作持久性 Cookie?

另一种方法是用可序列化类型替换不可序列化类型。例如使用byte[] content/String filename而不是InputStream/UploadedFile。或者直接在检索它的方法中将其写入(临时)文件,而不是将其分配为 bean 属性。另请参阅:

另请参阅:


为什么要序列化?

至于为什么您需要担心序列化,这是因为大多数 Java servlet 容器(例如 Tomcat)都要求类在这些类的实例存储为属性时实现 Serialized HttpSession。这是因为当 servlet 容器需要关闭/重新启动或被放置在会话具有的服务器集群中时,HttpSession 可能需要保存在本地磁盘文件系统上,甚至需要通过网络传输。进行同步。

为了能够将 Java 对象保存在本地磁盘文件系统上或通过网络传输它们,必须首先将它们转换为字节流(基本上:一个 byte[] 或一个 InputStream),并且只有当对象背后的类实现Serialized时才可能实现。 Serializable 接口本身并没有真正做任何事情,它只是一个标记接口。后面的代码仅对会话属性进行 instanceof Serializable 检查以采取相应的操作。

另请参阅:

Just implement Serializable

If you're getting a NotSerializableException like follows,

java.io.NotSerializableException: bean.ProjectAreaBean

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;

    // ...
}

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.

See also:


Mark unserializable fields 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, UploadedFile, etc), then you'd need to mark it transient. This way it will be skipped during serialization of the class.

private transient SomeObject thisWillNotBeSerialized;

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 a concrete example in this answer: How to make persistent Cookies with a DefaultHttpClient in Android?

The alternative is to replace the unserializable type by a serialiable type. E.g. using byte[] content/String filename instead of InputStream/UploadedFile. Or just write it to a (temp) file immediately within the method wherein you're retrieving it instead of assigning it as a bean property. See also:

See also:


Why serialization?

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.

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.

See also:

白衬杉格子梦 2024-08-29 07:30:34

您需要使 bean.ProjectAreaBean 可序列化。

You need to make bean.ProjectAreaBean serializable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文