前段时间做了壹個小的 Web 应用,跑在 Tomcat-7.0.47-x86 上,结果发现 Tomcat 容器启动时偶尔会抛出 java.io.NotSerializableException 异常,但是把 Tomcat 关闭之后再重启问题就不复存在。具体的错误堆栈信息如下所示:
严重: IOException while loading persisted sessions: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.shch.pats.service.AsynTradeExecutionServiceBean java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.shch.pats.service.AsynTradeExecutionServiceBean at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1352) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1597) at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1062) 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:491) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5443) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724)
在网上查了下,原来是因为我的壹個 Bean 的声明中没有实现接口 java.io.Serializable,只要在类的定义上添加上这句,问题就得到了圆满解决,Tomcat 也不会再抛出异常了。就像下面这样:
public class AsynTradeExecutionServiceBean implements java.io.Serializable { ... }
真是個奇怪的问题,序列化这东西还真是有点冒名其妙,弄不明白。另外我重点参考了
StackOverflow 的帖子:What causes a NotSerializableException in Tomcat 7,老外们在跟帖中是这麽说的:
1. Don't store non-serializable objects in the users session (generally a good practice). 2. Make your UserDAO serializable. Probably involves implementing the Serializable interface and marking your hibernateTemplate as transient as i don't think that HibernateTemplate is, in itself, serializable. You may have to add some code that re-initialize the hibernateTemplate on deserialization if you really want it to work. 3. Don't have Tomcat serializing sessions (add <Manager pathname="" /> to the context.xml, either in your own app or in the global tomcat context.xml in the conf/ directory, inside the <Context> element. This might be the best course of action for you, unless you really need sessions to be persisted across restarts.
这问题算是暂时解决了,有空再回来详细研究研究。