java.io.WriteAbortedException:写入中止; java.io.NotSerializedException
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果
您遇到
NotSerializedException
如下所示,那么它只是表示由异常消息中的完全限定名称标识的类(即
bean.ProjectAreaBean
在你的情况下)没有实现Serialized
接口,而这是后面的代码所期望的。修复它相对简单,只需让类实现Serialized
接口即可。serialVersionUID
字段不是必需的,但强烈建议使用,因为这可以保持类的不同版本及其实例的序列化表示之间的二进制兼容性。因此,当您稍后向类中添加新的可序列化字段时,您需要更改serialVersionUID
字段(通常只需将其增加 1 就足够了),以防止在反序列化实例的过程中出现问题。该类的旧版本。像 Eclipse 这样的 IDE 还提供了一个选项来(重新)生成serialVersionUID
值,该值基本上是基于所有字段计算的哈希值。另请参阅:
标记不可序列化字段
transient
如果你的
Serialized
类又包含一个引用另一个类的实例的字段/属性绝对不能可序列化
(通常,这些表示资源,例如InputStream
,Connection
,UploadedFile
等),那么您需要将其标记为transient
。这样,它将在类的序列化过程中被跳过。您需要了解,反序列化后该字段将始终变为
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
检查以采取相应的操作。另请参阅:
java.io.Serialized< /code> javadoc
Just implement
Serializable
If you're getting a
NotSerializableException
like follows,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 theSerializable
interface while it is been expected by the code behind. Fixing it is relatively simple, just let the class implement theSerializable
interface.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 theserialVersionUID
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 theserialVersionUID
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 madeSerializable
(usually, these represent resources, such asInputStream
,Connection
,UploadedFile
, etc), then you'd need to mark ittransient
. This way it will be skipped during serialization of the class.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 thereadObject()
andwriteObject()
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 ofInputStream
/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 theHttpSession
. That is because theHttpSession
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 anInputStream
) and that is only possible if the class behind the object implementsSerializable
. TheSerializable
interface itself doesn't really do anything, it's merely a marker interface. The code behind merely does aninstanceof Serializable
check on the session attribute to act accordingly.See also:
java.io.Serializable
javadoc您需要使
bean.ProjectAreaBean
可序列化。You need to make
bean.ProjectAreaBean
serializable.