引言

    tomcat属于web应用服务器,当我们的应用服务器关闭后,但是有些java class/thread/threadLocal等依然存活,当再次reload后,就会导致内存的溢出.为了避免这种严重的内存leak问题,tomcat做了一些内存溢出检测.

server.xml

  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

    虽然tomcat做了这些检测并试图stop这些存活的引用,但是不是强制的,比如一些请求或线程,当应用关闭的时候,还在处理中,这时tomcat不会去关闭.这就需要tomcat强制关闭或依赖对应的框架来关闭.


项目中遇到类似问题

Q1:
    org.apache.catalina.loader.WebappClassLoaderclearReferencesJdbc
SEVERE:The web application [/myapp] registered the JDBC driver[com.mysql.jdbc.Driver] but failed to unregister it when the web applicationwas stopped. To prevent a memory leak, the JDBC Driver has been forciblyunregistered.
 
A1:
https://stackoverflow.com/questions/15632153/tomcat7-jdbc-datasource-this-is-very-likely-to-create-a-memory-leak
需要把项目中使用的jdbc驱动包放到tomcat/lib
 
 
Q2:
org.apache.catalina.loader.WebappClassLoaderclearReferencesThreads
SEVERE: The web application [/myapp] appears to have started athread named [Abandoned connection cleanup thread] but has failed to stop it.This is very likely to create a memory leak.
 
A2:
   https://stackoverflow.com/questions/24850091/the-web-application-registered-the-jdbc-driver-com-mysql-jdbc-driver-but-fa
 
 
Q3:
SEVERE:The web application [/myapp] appears to have started a thread named [MySQL StatementCancellation Timer] but has failed to stop it. This is very likely to create amemory leak.
 
A3:
https://stackoverflow.com/questions/10615118/how-to-solve-memory-leak-problems
  这是mysql jdbc 驱动包的一个BUG(SUNVM), https://bugs.mysql.com/bug.php?id=36565
  version 5.1.27之后的版本解决了这个问题.
 
 
Q4:
org.apache.catalina.loader.WebappClassLoadercheckThreadLocalMapForLeaks
SEVERE: The web application [/myapp] created a ThreadLocal with keyof type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@681f8054]) and avalue of type [com.alibaba.druid.wall.spi.WallVisitorUtils.WallTopStatementContext](value[com.alibaba.druid.wall.spi.WallVisitorUtils$WallTopStatementContext@117d5a14])but failed to remove it when the web application was stopped. Threads are goingto be renewed over time to try and avoid a probable memory leak.
 
A4:
    关闭druid的自带监测功能.


tomcat 释放引用的主要分类


1. org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

  http://hongjiang.info/tomcat-jdbc-leak-prevention/

  https://stackoverflow.com/questions/15632153/tomcat7-jdbc-datasource-this-is-very-likely-to-create-a-memory-leak

 把JDBC driver放到tomcat/lib下,并删除项目的jdbc driver.


2. org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

http://hongjiang.info/tomcat-clear-references-threads/



3. org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

http://hongjiang.info/tomcat-clear-references-threadlocal/



4. clearReferencesRmiTargets



5.clearReferencesStaticFinal



6.clearReferencesResourceBundles


protected void clearReferences() {    // De-register any remaining JDBC drivers    clearReferencesJdbc();    // Stop any threads the web application started    clearReferencesThreads();    // Check for leaks triggered by ThreadLocals loaded by this class loader    checkThreadLocalsForLeaks();    // Clear RMI Targets loaded by this class loader    clearReferencesRmiTargets();    // Null out any static or final fields from loaded classes,    // as a workaround for apparent garbage collection bugs    if (clearReferencesStatic) {        clearReferencesStaticFinal();    }     // Clear the IntrospectionUtils cache.    IntrospectionUtils.clear();    // Clear the classloader reference in common-logging    if (clearReferencesLogFactoryRelease) {        org.apache.juli.logging.LogFactory.release(this);    }    // Clear the resource bundle cache    // This shouldn't be necessary, the cache uses weak references but    // it has caused leaks. Oddly, using the leak detection code in    // standard host allows the class loader to be GC'd. This has been seen    // on Sun but not IBM JREs. Maybe a bug in Sun's GC impl?    clearReferencesResourceBundles();    // Clear the classloader reference in the VM's bean introspector    java.beans.Introspector.flushCaches(); }


tomcat graceful shutdown

https://dzone.com/articles/tomcats-graceful-shutdown

http://www.captaindebug.com/2013/09/tomcats-graceful-shutdown-with-daemons.html#.Wdxh9ltL_IU





参考文档:

http://hongjiang.info/tomcat-jdbc-leak-prevention/

http://hongjiang.info/tomcat-clear-references-threads/

http://hongjiang.info/tomcat-clear-references-threadlocal/

http://blog.csdn.net/will_awoke/article/details/38338519

http://www.cnblogs.com/lixiaojiao-hit/p/5095180.html