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

问题描述 投票:0回答:2

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)
jakarta-ee tomcat java-io catalina notserializableexception
2个回答
63
投票

只需实施
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
UploadedFile
、等),那么你需要标记它
transient
。这样在类的序列化过程中它将被跳过。

private transient SomeObject thisWillNotBeSerialized;

你需要明白,反序列化后这个字段总是会变成

null
。请注意,在反序列化期间“不会”调用类的构造函数和初始化块。如果您想对序列化和反序列化进行更细粒度的控制,请重写 readObject()
writeObject()
方法。您可以在这个答案中找到一个具体的例子:
How to make permanent Cookies with a DefaultHttpClient in Android?
另一种方法是用可序列化类型替换不可序列化类型。例如。使用

byte[] content

/

String filename
代替
InputStream
/
UploadedFile
。或者直接在检索它的方法中将其写入(临时)文件,而不是将其分配为 bean 属性。另请参阅:
另请参阅:

    NotSerializedException 转换为InputStream时出现异常
  • 如何在JSF中保存上传的文件
  • 如何使用PrimeFaces p:fileUpload?监听器方法永远不会被调用或 UploadedFile 为 null / 抛出错误 / 不可用
为什么要序列化?

至于

为什么

,您需要担心序列化,这是因为大多数 Java servlet 容器(如 Tomcat)都需要类来实现 Serializable,只要这些类的实例存储为

HttpSession
 的属性即可。这是因为当 servlet 容器需要关闭/重新启动或被放置在会话必须同步的服务器集群中时,
HttpSession
可能需要保存在本地磁盘文件系统上,甚至需要通过网络传输。
为了能够将 Java 对象保存在本地磁盘文件系统上或通过网络传输它们,必须首先将它们转换为字节流(基本上:

byte[]

InputStream
),这是唯一可能的如果对象背后的类实现了
Serializable
Serializable
界面本身并没有真正做任何事情,它只是一个
标记界面。后面的代码只是对会话属性进行instanceof Serializable检查以采取相应的行动。
另请参阅:

  • java.io.Serializablejavadoc
    
    
  • Java 对象序列化规范
  • Java 教程 - 基本类 - 基本 I/O - 对象流

3
投票
bean.ProjectAreaBean

可序列化。

    

© www.soinside.com 2019 - 2024. All rights reserved.