是什么导致Tomcat 7中的NotSerializableException?

我的DAO实现在使用Tomcat7启动服务器时抛出了一个不可序列化的exception。 知道是什么原因引起的吗? 我的其他DAO都没有这样做。

这是class级:

package com.project.dao; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.orm.hibernate3.HibernateTemplate; import com.project.model.User; public class UserDAOImpl implements UserDAO { private HibernateTemplate hibernateTemplate; public void setSessionFactory(SessionFactory sessionFactory) { this.hibernateTemplate = new HibernateTemplate(sessionFactory); } @Override public void saveUser(User user) { hibernateTemplate.saveOrUpdate(user); } @Override @SuppressWarnings("unchecked") public List listUser() { return hibernateTemplate.find("from User"); } @Override @SuppressWarnings("unchecked") public User getUserByID(long userID) { List users= hibernateTemplate.find("from User where id = '" + userID + "'"); return users.size() > 0 ? users.get(0) : null; } } 

这是我的配置:

    com.mysql.jdbc.Driver   jdbc:mysql://localhost/context   someUser   somePassword         com.project.model.User     org.hibernate.dialect.MySQLDialect true true        

这是我的堆栈:

 SEVERE: IOException while loading persisted sessions: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.news.dao.UserDAOImpl java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.project.dao.UserDAOImpl at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350) at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1600) at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1073) at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:284) at org.apache.catalina.session.StandardManager.load(StandardManager.java:204) at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:470) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.startup.Catalina.start(Catalina.java:620) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431) Caused by: java.io.NotSerializableException: com.project.dao.UserDAOImpl at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330) at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1676) at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1090) at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:411) at org.apache.catalina.session.StandardManager.unload(StandardManager.java:353) at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:497) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5464) at java.lang.Thread.run(Thread.java:662) at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5481) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:502) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:748) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.startup.Catalina.stop(Catalina.java:693) at org.apache.catalina.startup.Catalina.start(Catalina.java:654) ... 6 more Jul 31, 2011 9:27:21 PM org.apache.catalina.session.StandardManager startInternal SEVERE: Exception loading sessions from persistent storage java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.project.dao.UserDAOImpl at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350) at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1600) at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1073) at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:284) at org.apache.catalina.session.StandardManager.load(StandardManager.java:204) at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:470) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.startup.Catalina.start(Catalina.java:620) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431) Caused by: java.io.NotSerializableException: com.project.dao.UserDAOImpl at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330) at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1676) at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1090) at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:411) at org.apache.catalina.session.StandardManager.unload(StandardManager.java:353) at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:497) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5464) at java.lang.Thread.run(Thread.java:662) at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5481) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:502) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:748) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225) at org.apache.catalina.startup.Catalina.stop(Catalina.java:693) at org.apache.catalina.startup.Catalina.start(Catalina.java:654) ... 6 more 

UserDaoImpl必须实现java.io.Serializable接口(如果要对其进行序列化)(您的堆栈跟踪指示尝试将类的实例写入对象流)。

要序列化的实例以及该实例的对象图中的所有对象都必须是可序列化的。

来自Serializable的javadocs,

实现java.io.Serializable接口的类启用了类的可序列化…当遍历图形时,可能会遇到不支持Serializable接口的对象。 在这种情况下,将抛出NotSerializableException,并将标识非可序列化对象的类。

请注意,这些规则有例外。 我建议您阅读Java对象序列化规范 ,以全面了解何时进行对象序列化以及避免NotSerializableException所需的内容。

它正在发生,因为代码中的某个地方,您正在会话中存储UserDAO(或者您正在存储一个引用UserDAO的对象)。 当您关闭所有活动会话时,Tomcat会尝试序列化所有活动会话的完整对象图,然后在您重新启动它时尝试恢复它们。 这方面的关键是Tomcat使用“普通”java对象序列化,这要求所有对象都是Serializable

如何补救:

  1. 不要在用户会话中存储不可序列化的对象(通常是一种很好的做法)。
  2. 使您的UserDAO可序列化。 可能涉及实现Serializable接口并将hibernateTemplate标记为transient因为我认为HibernateTemplate本身并不是可序列化的。 如果你真的希望它能够工作,你可能必须添加一些代码来重新初始化反序列化的hibernateTemplate。
  3. 没有Tomcat序列化会话(将到context.xml,在您自己的应用程序中或在元素内的conf /目录中的全局tomcat context.xml中。对你来说可能是最好的行动方案,除非你真的需要在重新启动时保持会话。

这里的其他答案很好地解释了序列化。 由于这是Google的第一个结果,我想添加真正帮助我解决问题的信息。

exception消息本身并不指示哪个类导致此问题。 如果你不能使类可序列化并且需要添加transient关键字以便Java不尝试序列化字段,那么找出导致问题的字段可能很棘手。

如果在启动时将参数-Dsun.io.serialization.extendedDebugInfo=true添加到Java / Tomcat,则exception将更加有用。 以下是exception消息的示例:

 java.io.NotSerializableException: za.co.abc.presentation.control.Three - field (class "za.co.abc.presentation.control.Two", name: "three", type: "class za.co.abc.presentation.control.Three") - object (class "za.co.abc.presentation.control.Two", za.co.abc.presentation.control.Two@fbbb20) - field (class "za.co.abc.presentation.control.One", name: "two", type: "class za.co.abc.presentation.control.Two") - object (class "za.co.abc.presentation.control.One", za.co.abc.presentation.control.One@17ee6c9) - field (class "za.co.abc.presentation.control.Trail", name: "one", type: "class za.co.abc.presentation.control.One") - root object (class "za.co.abc.presentation.control.Trail", {/click-tests/home.htm=home}) 

如果使用transient关键字使字段不是序列化,则可能必须在读取类时设置这些字段。 您必须实现readObject()方法才能执行此操作。 这是一个例子:

 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { // magically read all non-transient fields from input stream and populate their values in.defaultReadObject(); someTransientField = new NotSerializableClass(); }