Is this very likely to create a memory leak in Tomcat?

SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-269] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-270] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-271] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-272] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-273] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-274] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-275] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-276] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-277] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-278] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-279] but has failed to stop it. This is very likely to create a memory leak.
May 26, 2015 4:12:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/scheduler] appears to have started a thread named [Timer-280] but has failed to stop it. This is very likely to create a memory leak.

这会导致Tomcat 服务器停止后Java进程尚未停止, 继续占用内存, 必须通过 类似 kill -9 之类的命令去杀死java进程.

 

这是由于在服务器停止时有些线程尚未销毁所引起的, 如ThreadLocal; Scheduler 启动的线程; JDBC driver等.

在stackoverflow 上有几篇 专门讨论这问题的帖子并提供了一些解决办法.

http://stackoverflow.com/questions/4899205/tomcat-6-memory-leaks-log-entries

http://stackoverflow.com/questions/11872316/tomcat-guice-jdbc-memory-leak

http://stackoverflow.com/questions/5292349/is-this-very-likely-to-create-a-memory-leak-in-tomcat

 

在吸取他们的解决办法的基础上, 作进一步的总结, 认为在web.xml中添加一个ServletContextListener在Context destroy的时候做一些事情是不错的, 具体代码如下:

 

public class ContextDestroyListener implements ServletContextListener {

    private static Logger logger = LoggerFactory.getLogger(ContextDestroyListener.class);

    public static final List<String> MANUAL_DESTROY_THREAD_IDENTIFIERS = Arrays.asList("QuartzScheduler", "scheduler_Worker");

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //Ignore
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        destroyJDBCDrivers();
        destroySpecifyThreads();
    }

    private void destroySpecifyThreads() {
        final Set<Thread> threads = Thread.getAllStackTraces().keySet();
        for (Thread thread : threads) {
            if (needManualDestroy(thread)) {
                synchronized (this) {
                    try {
                        thread.stop();
                        logger.debug(String.format("Destroy  %s successful", thread));
                    } catch (Exception e) {
                        logger.warn(String.format("Destroy %s error", thread), e);
                    }
                }
            }
        }
    }

    private boolean needManualDestroy(Thread thread) {
        final String threadName = thread.getName();
        for (String manualDestroyThreadIdentifier : MANUAL_DESTROY_THREAD_IDENTIFIERS) {
            if (threadName.contains(manualDestroyThreadIdentifier)) {
                return true;
            }
        }
        return false;
    }

    private void destroyJDBCDrivers() {
        final Enumeration<Driver> drivers = DriverManager.getDrivers();
        Driver driver;
        while (drivers.hasMoreElements()) {
            driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.debug(String.format("Deregister JDBC driver %s successful", driver));
            } catch (SQLException e) {
                logger.warn(String.format("Deregister JDBC driver %s error", driver), e);
            }
        }
    }
}

 

来源于:http://blog.csdn.net/monkeyking1987/article/details/9182201

猜你喜欢

转载自singhoo.iteye.com/blog/2214500