Memory Leak Protection of Tomcat

在tomcat中停止和部署application时会有一些内存泄漏的检测,我以前也从没注意过,今天简单记录一下。
当使用shutdown.sh停止服务时,你也许会看到这样的日志:

INFO: HTMLManager: stop: Stopping web application at '/testWeb'
Mar 18, 2010 11:13:07 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [leakingThread] but has failed to stop it. This is very likely to create a memory leak.

如日志上所描述的,有一个leakingThread线程还在运行,很可能造成内存泄漏。根据官方wiki所解释,这是因为这个线程的ContextClassLoader持有了tomcat的Webapp Classloader而造成的。shutdown的时候扫描所有活着的线程,如果有线程的Thread ContextClassLoader是指向Webapp Classloader,导致Webapp Classloader无法被回收从而出现这个提示。当web应用创建一个线程时,默认,它的ContextClassLoader被设置是它parent线程,而在web应用中,parent线程就是tomcat的worker线程,worker线程的ContextClassLoader是在执行web应用的代码时被设置成Webapp Classloader。所以,很自然,你所创建的线程就持有Webapp Classloader的引用,除非你指定成其他的classloader。
要向避免这种问题,最根本就是要在web应用停止时正确地停止所有所创建的线程,比如在destroy方法,一般而言,框架所创建的线程,线程池都会正确地处理资源释放;当然如果有一些哈批框架,你可能就需要手动去设置线程的ContextClassLoader为null了。

ThreadLocal使用不当也会造成告警;

SEVERE: A web application created a ThreadLocal with key of type [test.MyThreadLocal] (value [test.MyThreadLocal@4dbb9a58]) and a value of type [test.MyCounter] (value [test.MyCounter@57922f46]) but failed to remove it when the web application was stopped. To prevent a memory leak, the ThreadLocal has been forcibly removed.

又是因为shutdown的时候web应用所创建的线程没有被适当关闭。当shutting down的时候,tomcat会检查所有的线程,线程的内部结构以及ThreadLocal...看看ThreadLocal的类(有可能继承ThreadLocal自己实现)和value是不是由Webapp Classloader所加载,如果是,那又碍着它被回收了,就抛出这个警告来。

上面只是列举了2种最常见的问题,还有一些tomcat内存泄漏的检查就不一一列举了,最重要的还是记得释放资源。

你可能感兴趣的:(Memory Leak Protection of Tomcat)