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 的项目,是否有任何最佳实践?是否有一些我必须编写的代码才能contextDestroyed正确关闭 c3p0 线程?

4

2 回答 2

2

我也面临同样的问题,我可以在我的 tomcat 控制台中看到以下警告

2014 年 7 月 30 日下午 3:20:16 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 在帖子中的一条评论建议添加自定义 ServletContextListener 并在侦听器的 contextDestroyed() 方法中显式关闭 C3P0 连接,该方法将在取消部署应用程序时执行。

我们没有完全使用代码,因为我们不想与 C3P0 硬耦合。但是我们意识到我们并没有在应用程序的任何地方关闭hibernate sessionFactory。我们在 ServletContextListener 的 contextDestroyed() 中添加了关闭休眠会话工厂的代码。现在我们没有错误,也没有在 tomcat 控制台中收到警告。

您可能还想阅读Hibernate:关闭会话工厂不会关闭 c3p0 连接池

于 2014-07-30T10:02:55.660 回答
2

一些想法:

1)如果您已将休眠应用程序的生命周期设置为映射到您的网络应用程序的生命周期(如果休眠和 c3p0 库位于您的网络应用程序的 lib 目录中,则绝对正确,即使没有也可能正确),您绝对需要确保c3p0 池在应用程序回收之前被销毁,通常意味着一种contextDestroyed方法。在hibernate-speak中,包装连接池的是SessionFactory;当您的应用程序在热重新部署时关闭时,请确保您的应用程序的 SessionFactory 已关闭()。应该有一个对称性:无论是在第一次请求中contextInitialized还是在第一次请求时,您的 SessionFactory 都应该被初始化。它应该在应用程序关闭时被销毁。

2) c3p0 的最新(仍是预发布)版本具有一些设置,旨在降低 c3p0 线程和源自过期 Web 应用 ClassLoader 的对象之间污染的可能性,特别是如果 c3p0 由非 Web 应用特定的 ClassLoader 加载(例如,如果 c3p0 库位于 $CATALINA_HOME/lib 而不是 webapp 库目录中)。如果您愿意升级到预发布版 [现在最新的是c3p0-0.9.5-pre5 ],请尝试以下新配置设置:

 c3p0.privilegeSpawnedThreads=true
 c3p0.contextClassLoaderSource=library

希望这可以帮助!

于 2013-11-11T14:08:30.867 回答