【问题标题】:What causes a NotSerializableException in Tomcat 7? [duplicate]是什么导致 Tomcat 7 中出现 NotSerializableException? [复制]
【发布时间】:2011-10-17 03:42:36
【问题描述】:

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

课程如下:

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<User> listUser() {
        return hibernateTemplate.find("from User");
    }

    @Override
    @SuppressWarnings("unchecked")
    public User getUserByID(long userID) {
        List<User> users= hibernateTemplate.find("from User where id = '" + userID + "'");
        return users.size() > 0 ? users.get(0) : null;
    }
}

这是我的配置:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <bean id="myDataSource" 
    class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
      <property name="driverClassName">
        <value>com.mysql.jdbc.Driver</value>
      </property>
      <property name="url">
        <value>jdbc:mysql://localhost/context</value>
      </property>
      <property name="username">
        <value>someUser</value>
      </property>
      <property name="password">
        <value>somePassword</value>
      </property>
      <!-- Disable the second-level cache  -->
        <!-- Echo all executed SQL to stdout -->
    </bean>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" /> 
        <property name="annotatedClasses">
            <list>
                <value>com.project.model.User</value>
            </list>
        </property> 
        <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
        </property>
    </bean>
    <bean id="myUserDAO" class="com.project.dao.UserDAOImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean> 
</beans>

这是我的堆栈:

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

【问题讨论】:

  • 您是在会话中的某处设置此对象还是将其设置为存储在会话中的对象的变量?
  • 它是一个对象中的变量,存储在会话中。
  • 然后删除它,因为这个对象可以访问 Hibernate 会话,它永远无法序列化自己。

标签: java tomcat7 notserializableexception


【解决方案1】:

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

异常消息本身并不指示哪个类中的哪个字段导致了此问题。如果您无法使类可序列化并且需要添加瞬态关键字,以便 Java 不会尝试序列化字段,则可能很难确定是哪个字段导致了问题。

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

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})

如果您确实使用瞬态关键字使字段不序列化,您可能必须在读取类时设置这些字段。您必须实现 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();
}

【讨论】:

  • +1 for -Dsun.io.serialization.extendedDebugInfo=true,即使对于独立的 Java 应用程序也非常有用。
【解决方案2】:

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

如何补救:

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

【讨论】:

  • 我需要说这个。你的回答很棒。对我帮助很大,谢谢。
【解决方案3】:

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

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

来自 Serializable 的 javadocs,

类的可序列化性由实现 java.io.Serializable接口...遍历图时,对象 可能会遇到不支持 Serializable 接口的情况。 在这种情况下,将抛出 NotSerializableException 并将 识别不可序列化对象的类。

请注意,这些规则也有例外。我建议您阅读Java Object Serialization Specification 以全面了解对象序列化何时发生以及如何避免 NotSerializableException。

【讨论】:

  • 这不是特别有用的信息。 OP 需要知道为什么在启动期间会发生这种情况,而不是关于序列化机制的详细信息。
  • 这可能是近端原因,但不是根本原因。您如何建议使 HibernateTemplate 可序列化?
  • 序列化 spring 管理的 bean 不是一个好主意。
猜你喜欢
  • 2023-03-02
  • 2016-10-26
  • 2014-11-05
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
相关资源
最近更新 更多