web-dev-qa-db-ja.com

Tomcat 7でNotSerializableExceptionが発生する原因は何ですか?

私の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
21
coder

UserDaoImplは、シリアル化する場合は Java.io.Serializable インターフェイスを実装する必要があります(スタックトレースは、クラスのインスタンスをオブジェクトストリームに書き込もうとしていることを示します)。

シリアル化されるインスタンスは、そのインスタンスのオブジェクトグラフ内のすべてのオブジェクトとともに、すべてシリアル化可能でなければなりません。

Serializableのjavadocsから、

クラスの直列化可能性は、Java.io.Serializableインターフェースを実装するクラスによって有効になります...グラフをトラバースすると、Serializableインターフェースをサポートしないオブジェクトが検出される場合があります。この場合、NotSerializableExceptionがスローされ、シリアル化できないオブジェクトのクラスを識別します。

これらの規則には例外があることに注意してください。オブジェクトのシリアル化がいつ行われ、NotSerializableExceptionを回避するために何が必要かを完全に理解するには、 Java Object Serialization Specification を読むことをお勧めします。

21

コードのどこかで、セッションにUserDAOを保存している(または、UserDAOへの参照を持つオブジェクトを保存している)ために発生しています。 Tomcatは、シャットダウン時にすべてのアクティブセッションの完全なオブジェクトグラフをシリアル化しようとし、その後、起動時にそれらを復元しようとします。これの核心は、Tomcatが「通常」Javaオブジェクトのシリアル化を使用するため、すべてのオブジェクトがSerializableである必要があるということです。

対処方法:

  1. シリアル化できないオブジェクトをユーザーセッションに保存しないでください(一般的には良い方法です)。
  2. UserDAOをシリアル化可能にします。おそらくSerializableインターフェイスを実装し、transient自体がシリアル化可能であるとは思わないので、hibernateTemplateをHibernateTemplateとしてマークする必要があります。本当に動作させるには、デシリアライズ時にhibernateTemplateを再初期化するコードを追加する必要があります。
  3. Tomcatのシリアル化セッションを持たない(独自のアプリまたはconf /ディレクトリのグローバルTomcat context.xmlの<Manager pathname="" />要素内で、<Context>をcontext.xmlに追加します。これは再起動後もセッションを永続化する必要が本当にない限り、あなたにとって最善の行動方針です。
32
pap

ここでの他の回答は、シリアル化についてよく説明しています。これはGoogleでの最初の結果であるため、問題の解決に本当に役立つ情報を追加したかったのです。

例外メッセージ自体は、どのクラスのどのフィールドがこの問題を引き起こしたかを示していません。クラスをシリアル化できず、一時的なキーワードを追加する必要がある場合、Javaはフィールドをシリアル化しようとしないため、問題の原因となっているフィールドを把握するのが難しい場合があります。

パラメータ-Dsun.io.serialization.extendedDebugInfo=trueをJava/Tomcatの起動時に追加すると、例外がはるかに便利になります。例外メッセージの表示例を次に示します。

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();
}
13
Sarel Botha