一個項目通過c3p0獲得連接池,相關代碼如下:
public class JdbcUtil {
// 連接池的核心類
private static ComboPooledDataSource dataSource;
//初始化連接池相關參數
static{
try {
dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(PropertiesUtil.getValue("jdbcName"));
dataSource.setJdbcUrl(PropertiesUtil.getValue("dbUrl"));
dataSource.setUser(PropertiesUtil.getValue("dbUserName"));
dataSource.setPassword(PropertiesUtil.getValue("dbPassword"));
dataSource.setInitialPoolSize(5);
dataSource.setMinPoolSize(5);
dataSource.setMaxPoolSize(20);
// 以下兩句用於設置自動重連
dataSource.setIdleConnectionTestPeriod(10);
dataSource.setTestConnectionOnCheckin(true);
} catch (Exception e) {
e.printStackTrace();
}
}
//下面是getDataSource,getConnection等方法
}
關閉Tomcat的時候提示可能會造成內存泄漏:
警告: The web application [uavmonitor] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.util.TimerThread.mainLoop(Timer.java:552)
java.util.TimerThread.run(Timer.java:505)
二月 13, 2017 3:51:45 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: The web application [uavmonitor] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
二月 13, 2017 3:51:45 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: The web application [uavmonitor] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
二月 13, 2017 3:51:45 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: The web application [uavmonitor] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
主要是這句:
警告: The web application [uavmonitor] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
與這句
The web application [uavmonitor] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.util.TimerThread.mainLoop(Timer.java:552)
java.util.TimerThread.run(Timer.java:505)
查詢c3p0官方文檔
說明如下:c3p0 spawns a variety of Threads (helper threads, java.util.Timer threads),結合上面的出錯信息,推斷應該是Tomcat關閉的時候沒有關閉JdbcUtil類創建出來的c3p0的datasource。
解決方案
寫一個監聽器,在其public void contextDestroyed方法中進行對c3p0數據源進行關閉就可以解決相關問題。
try {
DataSources.destroy(JdbcUtil.getDataSource());//getDataSource方法獲取c3p0數據源
System.out.println("關閉數據庫連接池成功!");
} catch (SQLException e) {
e.printStackTrace();
}
如果運行在Tomcat中的代碼啟動了Executor線程池,也需要在適當的地方(比如監聽器中的contextDestroyed方法)進行shutdown,否則會造成資源泄露。
從這個例子中也可以看出,直接使用spring、mybatis等管理數據源是多么省事。
