从 Tomcat 取消部署应用程序时,有一些线程处于打开状态。
org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/services] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak.
org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/services] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak.
该应用程序维护一个 DataSources 的映射并运行 ScheduledExecutorService 以每 5 分钟更新一次映射。
@WebListener
public class DataSourceFactory implements ServletContextListener
{
private static Map<String, DataSource> rdsDataSourceMap;
private static ScheduledExecutorService scheduler;
private static final long CONNECTION_MAP_REFRESH_INTERVAL = 5;
@Override
public void contextInitialized(ServletContextEvent event)
{
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
cacheDatasourceMap();
}
}, 0, CONNECTION_MAP_REFRESH_INTERVAL, TimeUnit.MINUTES);
}
@Override
public void contextDestroyed(ServletContextEvent event)
{
scheduler.shutdownNow();
if (localPool != null) {
localPool.close();
}
for (DataSource ds : rdsDataSourceMap.values()) {
if (ds != null) {
ds.close();
}
}
}
private void cacheDatasourceMap()
{
...
}
....
}
数据源是使用 TomcatJDBC 创建的,具有以下参数:
driver=com.mysql.jdbc.Driver
jmxEnabled=true
testWhileIdle=true
testOnBorrow=true
validationQuery=SELECT 1
testOnReturn=false
validationInterval=30000
timeBetweenEvictionRunsMillis=5000
maxActive=100
maxIdle=20
initialSize=10
maxWait=100000
removeAbandonedTimeout=60
minEvictableIdleTimeMillis=30000
minIdle=10
logAbandoned=true
removeAbandoned=true
jdbcInterceptors=org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx(threshold=10000)
更新
摆脱后,ScheduledExecutorService
我仍然看到 Timer 线程处于打开状态。我在末尾添加了一条日志记录语句,contextDestroyed()
并验证它是否已通过关闭数据源。
我还验证了 Tomcat 库中的 MySQL 驱动程序,而不是 WAR 中的 MySQL 驱动程序。