2

プロジェクトが tomcat 7 で netbeans を介して再デプロイされると、次のようなエラーが発生します

java.lang.IllegalStateException
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    at com.mchange.v2.resourcepool.BasicResourcePool.checkIdleResources(BasicResourcePool.java:1481)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$2000(BasicResourcePool.java:32)
    at com.mchange.v2.resourcepool.BasicResourcePool$CheckIdleResourcesTask.run(BasicResourcePool.java:1964)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
Exception in thread "Timer-5" java.lang.NoClassDefFoundError: com/mchange/v2/resourcepool/BasicResourcePool$AsyncTestIdleResourceTask
    at com.mchange.v2.resourcepool.BasicResourcePool.checkIdleResources(BasicResourcePool.java:1481)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$2000(BasicResourcePool.java:32)
    at com.mchange.v2.resourcepool.BasicResourcePool$CheckIdleResourcesTask.run(BasicResourcePool.java:1964)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
Caused by: java.lang.ClassNotFoundException: com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    ... 5 more

今日、Tomcat 7 でプロジェクトを再デプロイしようとしたときに、別の奇妙なエラーが発生しました。

[5:07:02 PM] Nitin - Webscraper/Tester,Java/PHP developer: java.lang.NoClassDefFoundError: com/mchange/v2/lang/VersionUtils
 com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:104)
 com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
 com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:62)
 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:531)
 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
 org.hibernate.connection.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:78)
 org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
 org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
 org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
 org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1700)
 org.hibernate.loader.Loader.doQuery(Loader.java:801)
 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
 org.hibernate.loader.Loader.doList(Loader.java:2542)
 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
 org.hibernate.loader.Loader.list(Loader.java:2271)

かなり前から、このような奇妙なエラーが発生しています。デバッグしようとすると、クラスが既に存在することがわかります。

私が考えることができるのは、c3p0 接続プーリング スレッドがぶら下がっていることです。これは、再デプロイ時に適切に破棄されないか、アクティブな接続が実行されているか、または同様のものが実行されている可能性があります。

hibernate と c3p0 を使用するこのようなプロジェクトを再デプロイする方法に関するベスト プラクティスはありますか? contextDestroyedc3p0 スレッドを適切に閉じるために記述しなければならないコードはありますか?

4

2 に答える 2

2

私も同じ問題に直面しており、Tomcat コンソールに以下の警告が表示されました。

2014 年 7 月 30 日 3:20:16 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads 警告: Web アプリケーション [/rmlcrm] は、[C3P0PooledConnectionPoolManager[identityToken->1hge50p9311d8syo1hfjimz|19ddf1db]-HelperThread-# という名前のスレッドを開始したようです。 0] しかし、それを停止できませんでした。これにより、メモリ リークが発生する可能性が非常に高くなります。スレッドのスタック トレース: java.lang.Object.wait(Native Method) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:635)

私はこれに対する解決策を見つけるために多くのことを読んでいて、 Hibernate :OutOfMemoryError: PermGen spaceの投稿に出くわしました

Nicholas Hemley による投稿のコメントの 1 つは、カスタム ServletContextListener を追加し、アプリケーションがアンデプロイされたときに実行されるリスナーの contextDestroyed() メソッドで C3P0 接続を明示的に閉じることを提案しました。

C3P0 とハードカップリングしたくないので、コードを正確には使用しませんでした。しかし、アプリケーションのどこでも hibernate sessionFactory を閉じていないことに気付きました。ServletContextListener の contextDestroyed() で休止状態のセッション ファクトリを閉じるコードを追加しました。これで、エラーは発生せず、Tomcat コンソールにも警告が表示されなくなりました。

Hibernateも参照してください。セッション ファクトリを閉じても、c3p0 接続プールは閉じられません。

于 2014-07-30T10:02:55.660 に答える
2

いくつかの考え:

1) Web アプリのライフサイクルにマップするように休止状態アプリのライフサイクルを設定している場合 (休止状態と c3p0 ライブラリが Web アプリの lib ディレクトリに存在する場合は間違いなく true であり、そうでない場合でも潜在的に true である可能性があります)、絶対に確認する必要があります。 c3p0 プールは、アプリケーションのリサイクル前に破棄されます。これは、多くの場合、contextDestroyedメソッドを意味します。休止状態で言えば、接続プールをラップするのは SessionFactory です。アプリケーションがホット再デプロイでシャットダウンするときに、アプリケーションの SessionFactory が close() されていることを確認してください。対称性が必要contextInitializedです。最初のリクエストで、または遅延して、SessionFactory を初期化する必要があります。アプリケーションのシャットダウン時に破棄する必要があります。

2) c3p0 の最新 (まだプレリリース) バージョンには、c3p0 スレッドと期限切れの Web アプリ ClassLoader から派生したオブジェクトとの間の汚染の可能性を減らすように設計されたいくつかの設定があります。特に c3p0 が非 Web アプリ固有の ClassLoader (たとえば、c3p0 ライブラリが webapp lib ディレクトリではなく $CATALINA_HOME/lib にある場合)。プレリリース [現在の最新はc3p0-0.9.5-pre5 ] にアップグレードする場合は、次の新しい構成設定を試してください。

 c3p0.privilegeSpawnedThreads=true
 c3p0.contextClassLoaderSource=library

お役に立てれば!

于 2013-11-11T14:08:30.867 に答える