Class loader - the memory leak problem of 2

Serious warning: If there is any application other than from a reference cited by the J2EE application itself class loader loads the class and class instance object, then ClassLoader class loader memory leak problem arises.

ClassLoader class loader memory leak problem of positioning

As noted above Classloader class loading is a memory leak is due to start repeating, stop application led to repeated load Class and object reference as the relationship between system level, leading to the previously created class can not be recovered, leading to memory leaks.

ClassLoader class load positioning the root of the memory leak is still very difficult, because any existing JVM Profiling tools can not ClassLoader perspective to analyze the current memory of the existence of Class class. Currently we can only generate JVM Heapdump way to identify whether there ClassLoader class loader memory leak, then the above class loader ClassLoader memory leak generating mechanism for troubleshooting problems that may occur, ultimately solve the problem.

Seems to concentrate in JDK6 tool provides the tools to locate the problem. Please refer to

To simplify troubleshooting and positioning applications, you may ClassLoader memory leak in the process of class loading, for which we have listed a number of class loading can cause Classloader memory leak code and components: (We are not here to roll out coverage on the following components of the root cause memory leaks, as our work on it! haha)

a) application or use of the components used java.util.logging.Level that you have to pay attention.

b) If you use such as DBCP and other development on the basis of DriverManager API database connection pool component, if the underlying design of ill-considered, can easily lead to class loading Classloader memory leak.

c) If you are using to commons-logging component (which is a lot of OpenSource components are dependent on commons-logging), it is almost certain to occur Classloader class loader memory leak. Because as WebSphere, Tomcat and other servers use the same core engine to the commons-logging component, and before the application starts commons-logging has been a lot of class ClassLoader loaded system level. By default, a type of load JVM class loader from the start, so that commons-logging system, the priority application EAR is generally higher than those contained in commons-logging, class loader so Classloader memory leak there may appear. Simple analysis of the problem as follows:

1) We generally use the commons-logging application's API to get the Log: protected final Log logger = LogFactory. GetLog (getClass ()).

2) To this end we analyze the commons-logging library in LogFactory class, note in which factories are class static variable, but getFactory () method is a static method, belong to the class attribute.
By the following code we can clear that: if LogFactory application EAR on a loading path in the class is loaded, then loaded in the application class loader to create the LogFactory instance (no matter org.apache.commons. logging.impl.LogFactoryImpl or org.apache.commons.logging.impl.Log4jFactory), will be on a class loader in the LogFactory classes mandatory reference and stored in a static class properties variable factories.
Guer even if the application of force to stop the EAR, but because the system class loader loaded LogFactory mandatory reference in the factories created LogFactory this application instance object can not be garbage collection, from the lead all the Class can not be destroyed, the final formation of Classloader class loading memory leak.

view plain print?

  1. public abstract class LogFactory (
  2. protected static Hashtable factories = null;
  3. ... ...
  4. public static Log getLog (Class clazz) throws LogConfigurationException (
  5. return getFactory (). getInstance (clazz);
  6. )
  7. public abstract Log getInstance (Class class1) throws LogConfigurationException;
  8. ... ...
  9. public static LogFactory getFactory () throws LogConfigurationException (
  10. ClassLoader contextClassLoader = getContextClassLoader ();
  11. LogFactory factory = getCachedFactory (contextClassLoader);
  12. if (factory! = null)
  13. return factory;
  14. ... ...
  15. / / The following code is deleted a lot, mainly used for: to create a new LogFactory loaded by the application object factory
  16. ... ...
  17. if (factory! = null) (
  18. cacheFactory (contextClassLoader, factory);
  19. ... ...
  20. )
  21. return factory;
  22. )
  23. private static void cacheFactory (ClassLoader classLoader, LogFactory factory) (
  24. if (factory! = null)
  25. if (classLoader == null)
  26. nullClassLoaderFactory = factory;
  27. else
  28. factories.put (classLoader, factory);
  29. )
  30. ... ...
  31. )

d) place the log4j library to the system class path (eg: JVM, WebSphere Extensions Class loader, WebSphere lib / app Class loader, WebSphere "server" Class loader class path), and use log4j's "Context Repository Selector" mode application access to all logging configuration.
If the time application EAR / WAR contains log4j library will be a Class Cast Exceptions Exception not functioning; if the application EAR / WAR does not contain log4j library, although the applications run normally, but will lead to class loading Classloader memory leak. On log4j's "Context Repository Selector" mode, please refer to

e) If you develop a component to be used java.beans.Introspector Class / Method MetaData cache may trigger class loading Classloader memory leak.
Analysis of Java Bean for each property, method is more consumption of CPU resources, so in many of the framework-level components such as Spring in the widespread use of cache JavaBean java.beans.Introspector to Cache definition, Introspector class will use the private static Map beanInfoCache = Collections. synchronizedMap (new WeakHashMap ()) class static variable approaches to the definition of preservation JavaBean.
The Introspector is loaded by the system JVM ClassLoader, so applications will be defined JavaBean Class System class loader loads the Introspector mandatory reference, leading to a state in the application is stopped, all associated with this application class can not be recovered.
Introspector specific code as follows:

view plain print?

  1. package java.beans;
  2. ... ...
  3. public class Introspector (
  4. ... ...
  5. private static Map declaredMethodCache = Collections.synchronizedMap (new WeakHashMap ());
  6. private static Map beanInfoCache = Collections.synchronizedMap (new WeakHashMap ());
  7. ... ...
  8. public static BeanInfo getBeanInfo (Class <?> beanClass) throws IntrospectionException
  9. (
  10. if (! ReflectUtil.isPackageAccessible (beanClass)) (
  11. return (new Introspector (beanClass, null, USE_ALL_BEANINFO)). getBeanInfo ();
  12. )
  13. BeanInfo bi = (BeanInfo) beanInfoCache.get (beanClass);
  14. if (bi == null) (
  15. bi = (new Introspector (beanClass, null, USE_ALL_BEANINFO)). getBeanInfo ();
  16. beanInfoCache.put (beanClass, bi);
  17. )
  18. return bi;
  19. )
  20. ... ...
  21. )

We can also note in the Spring org.springframework.beans.CachedIntrospectionResults class in Spring clear that there may be a memory leak Introspection Classloader class load: "Internal class that caches JavaBeans (@ link java.beans.PropertyDescriptor) information for a Java class. Not intended for direct use by application code. Necessary for own caching of descriptors within the application's ClassLoader, rather than rely on the JDK's system-wide BeanInfo cache (in order to avoid leaks on ClassLoader shutdown). "
In CachedIntrospectionResults in the same class used to cache static variable classCache class definition, if a stock is to apply the class Spring class loader of the JVM on a system or application server class path, then the class loader may lead to Classloader memory leak .
CachedIntrospectionResults specific code as follows: (Note: for Spring2.0.7 later version)

view plain print?

  1. package org.springframework.beans;
  2. ......
  3. final class CachedIntrospectionResults
  4. (
  5. private static final Log logger;
  6. private static final Map classCache = Collections.synchronizedMap (new WeakHashMap ());
  7. private final BeanInfo beanInfo;
  8. private final Map propertyDescriptorCache;
  9. static
  10. (Logger = LogFactory.getLog (org.springframework.beans.CachedIntrospectionResults.class);)
  11. public static CachedIntrospectionResults forClass (Class beanClass)
  12. throws BeansException
  13. (
  14. CachedIntrospectionResults results = null;
  15. Object value = classCache.get (beanClass);
  16. ... ...
  17. if (results == null)
  18. (
  19. results = new CachedIntrospectionResults (beanClass);
  20. boolean cacheSafe = isCacheSafe (beanClass);
  21. if (logger.isDebugEnabled ())
  22. logger.debug ("Class [" + beanClass.getName () + "] is" + (cacheSafe? "": "not") + "cache-safe");
  23. if (cacheSafe)
  24. classCache.put (beanClass, results);
  25. else
  26. classCache.put (beanClass, new WeakReference (results));
  27. ) Else
  28. if (logger.isDebugEnabled ())
  29. logger.debug ("Using cached introspection results for class [" + beanClass.getName () + "]");
  30. return results;
  31. )
  32. private CachedIntrospectionResults (Class clazz) throws BeansException
  33. (
  34. ... ...
  35. beanInfo = Introspector.getBeanInfo (clazz);
  36. Class classToFlush = clazz;
  37. ... ...
  38. )
  39. ... ...
  40. )

f) in the commons-beanutils 1.7 version (including 1.7 version) of the component class loader exists Classloader memory leak, only the latest 1.8.0Beta corrected this potential problem,
Problem description:
* [BEANUTILS-59] - Memory leak on webapp undeploy in WrapDynaClass
* [BEANUTILS-156] - Memory leak on webapp undeploy in MappedPropertyDescriptor
Detailed description please refer to:

g) used in the application of MethodUtils commons-beanutils to the methods of the class Method to operate, it also exists Classloader class loader memory leak possible.
If commons-beanutils library placed on the application-level class loading path, and there are other applications (or system code) prior to use in this application the same way MethodUtils to operate on the Class's Method (in the other class loader loading MethodUitls), then the Classloader class loading inevitable memory leak. We can refer to MethodUtils the corresponding code can be very intuitive positioning:

view plain print?

  1. package org.apache.commons.beanutils;
  2. ... ...
  3. public class MethodUtils
  4. (
  5. private static WeakHashMap cache = new WeakHashMap ();
  6. ... ...
  7. public static Method getAccessibleMethod (Class clazz, String methodName, Class parameterTypes [])
  8. (
  9. MethodDescriptor md;
  10. Method method;
  11. md = new MethodDescriptor (clazz, methodName, parameterTypes, true);
  12. method = (Method) cache.get (md);
  13. if (method! = null)
  14. return method;
  15. try (
  16. method = getAccessibleMethod (clazz.getMethod (methodName, parameterTypes));
  17. cache.put (md, method);
  18. return method;
  19. ) Catch (NoSuchMethodException e) (
  20. return null;
  21. )
  22. ... ...
  23. )

h) If the application using the Java 1.5 syntax defined enum class, and this defines the class placed in the application-level class loading path. First, we develop the application in the class loader to load and initialize the application-defined enum class, then other applications EAR / WAR (or system code) also uses this definition of the enum type, in and to such enum attribute references placed (for other applications) class Servlet static variable or class variable, then we develop the application Classloader class loader will not be recycled and eventually inevitable memory leak. For example:

view plain print?

  1. package com.test.enumeration;
  2. public enum OperationEnum (
  3. QUOTE (1), ISSUE (2), RENEW (4), CANCEL (12),
  4. ENDORSE (16), CHANGE (64), REINSTATE (192);
  5. private int operation = 0;
  6. private OperationEnum (int op) (
  7. this. operation = op;
  8. )
  9. public boolean isNewOperation () (
  10. return (this. operation == 2) | |
  11. (This. Operation == 4) | |
  12. (This. Operation == 192);
  13. )
  14. )

Other applications use the EAR to the above sample code defines enum class

view plain print?

  1. public class LeakCauseServletInOtherApp extends HttpServlet (
  2. private final OperationEnum operation = OperationEnum.CHANGE; / /
  3. protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException (
  4. doSomething (request, response);
  5. )
  6. ... ...
  7. )

i) result in class loading Classloader memory leak is another important factor: if the framework or application to use ThreadLocal thread-data space to store the instance of the object, you need to know in WAS and other application server instances are of the thread pool state, the WebContainer by the application server containers such as to maintain the thread instance.
Even if the application is stopped, and the state of the thread pool instance will still be viable operations, if the application Web Servlet thread running process instances are stored in the ThreadLocal object is not properly removed, can cause the thread class loader memory leak problem.
In the old version of DOM4J, Mozilla Rhino, CGLIB there this type of thread memory leak, please use the latest version of these components to avoid the occurrence of such leakage.

1) Hibernate 3.2.2 version of the thread ThreadLocal variable exists in the memory leak problem in version 3.2.3 be modified. For details, please refer to "Big Memory leak in the use of CGLIB"

2) CGLIB 2.1 memory leak exists ThreadLocal thread-variable problem, in the latest version 2.1_3 of the problem should be modified. For more information see

3) dom4j 1.6 version before the existence of variable memory leaks ThreadLocal thread in the 1.6 version later this issue is resolved.
Problem Description: https: / / / tracker / index.php? Func = detail & aid = 1070309 & group_id = 16035 & atid = 116035
Bug revised description: "Added a SingletonStrategyclass for managing singletons. This allows to use different strategies for singletons, like: one instance per VM, one instance per thread, ... This change removed the usage of ThreadLocals."

ClassLoader class loader memory leak problem solution

ClassLoader class loader memory leak problem solving principles:

1, do not apply to use of the library onto the JRE or WebSphere server class loader path, try to use the library to keep the EAR or WAR / WEB-INF / Lib path.

2, as set in the WebSphere server class loading order "Child-First ClassLoaders" / "Parent-Last ClassLoaders".

3, for DOM4J, Mozilla Rhino, CGLIB Make sure to use the latest version, and confirm the library stored in the application under the EAR level.

4, try to avoid using Java 1.5 syntax of enum class, if you use the enum class, to be sure to keep the development of libraries in the application EAR class loader under this level, but must not be placed or JVM library path to the WebSphere in.

5, using the latest version of commons-logging, and confirm the library stored in the application under the EAR level.

6, using the latest version of commons-beanutils, and confirm the library stored in the application under the EAR level, do not be put into WebSphere or JVM library path.

7, using the latest version of log4j, and confirm the library stored in the application under the EAR level, do not be put into WebSphere or JVM library path.

8, do not use in a production environment DriverManager.

9, do not use in a production environment as commons-dbcp data source implementation, recommended application server data source.

10, do not use in applications java.util.logging.Level.

Unable to avoid the commons-logging inventory is WebSphere Application Server class path and a large number of J2EE OpenSource class component uses java.beans.Introspector to the fact that the definition of Cache cache JavaBean for this situation and how we respond to and deal with it?

As we repeat the above Class loading problem to reproduce prepared ClassLoaderTestServlet sample, using the most simple way to call a Spring managed object class instance StaticClass sc, took place on the notorious Class class loader memory leak problem. How to avoid this problem happening?

Memory leak problem for java.beans.Introspector

In fact, later in the Spring framework version 2.0.7 has been corresponding with this solution provides a dedicated memory leak problem Java.beans.Introspector helper classes: org.springframework.web.util.IntrospectorCleanupListener, together with there are special instructions document description. If the original document as follows:


Listener that flushes the JDK's JavaBeans Introspector cache on web app shutdown. Register this listener in your web.xml to guarantee proper release of the web application class loader and its loaded classes.

If the JavaBeans Introspector has been used to analyze application classes, the system-level Introspector cache will hold a hard reference to those classes. Consequently, those classes and the web application class loader will not be garbage-collected on web app shutdown! This listener performs proper cleanup, to allow for garbage collection to take effect.

Unfortunately, the only way to clean up the Introspector is to flush the entire cache, as there is no way to specifically determine the application's classes referenced there. This will remove cached introspection results for all other applications in the server too.

Note that this listener is not necessary when using Spring's beans infrastructure within the application, as Spring's own introspection results cache will immediately flush an analyzed class from the JavaBeans Introspector cache and only hold a cache within the application's own ClassLoader. Although Spring itself does not create JDK Introspector leaks, note that this listener should nevertheless be used in scenarios where the Spring framework classes themselves reside in a 'common' ClassLoader (such as the system ClassLoader). In such a scenario, this listener will properly clean up Spring's introspection cache.

Application classes hardly ever need to use the JavaBeans Introspector directly, so are normally not the cause of Introspector resource leaks. Rather, many libraries and frameworks do not clean up the Introspector: eg Struts and Quartz.

Note that a single such Introspector leak will cause the entire web app class loader to not get garbage collected! This has the consequence that you will see all the application's static class resources (like singletons) around after web app shutdown, which is not the fault of those classes!

This listener should be registered as the first one in web.xml, before any application listeners such as Spring's ContextLoaderListener. This allows the listener to take full effect at the right time of the lifecycle.


In the above documents, we can clear that, if put to the Spring library system or application server, a JVM-level library path, we must configure org.springframework.web.util.IntrospectorCleanupListener in web.xml in order to prevent possible Introspector Spring in a memory leak.

web.xml sample configuration is as follows:

configuration file web.xml (this Spring Listener only exist until a future release Spring2.0)

view plain print?

  1. <? Xml version = "1.0" encoding = "UTF-8"?>
  2. <Web-app id = "WebApp_ID" version = "2.4"
  3. xmlns = ""
  4. xmlns: xsi = ""
  5. xsi: schemaLocation = "">
  6. <Display-name> ClassLoader </ display-name>
  7. <Context-param>
  8. <Param-name> contextConfigLocation </ param-name>
  9. <Param-value> classpath *: spring / *. xml </ param-value>
  10. </ Context-param>
  11. <! - Spring Refresh Introspector prevent memory leaks, recommend to the Listener in the first place, at least in the first Spring Related Listener ->
  12. <Listener>
  13. <Listener-class> org.springframework.web.util.IntrospectorCleanupListener </ listener-class>
  14. </ Listener>
  15. <Listener>
  16. <Listener-class> org.springframework.web.context.ContextLoaderListener </ listener-class>
  17. </ Listener>
  18. ... ...

org.springframework.web.util.IntrospectorCleanupListener sample code as follows: (for the Spring 2.0.7 or later code)

view plain print?

  1. package org.springframework.web.util;
  2. ... ...
  3. public class IntrospectorCleanupListener implements ServletContextListener (
  4. public void contextInitialized (ServletContextEvent event) (
  5. CachedIntrospectionResults.acceptClassLoader (Thread.currentThread (). GetContextClassLoader ());
  6. )
  7. public void contextDestroyed (ServletContextEvent event) (
  8. CachedIntrospectionResults.clearClassLoader (Thread.currentThread (). GetContextClassLoader ());
  9. Introspector.flushCaches ();
  10. )
  11. )

WebSphere Application Server class path for the existing library commons-logging, commons-logging applications, the use of lead ClassLoader class loader memory leak problem

In fact, for the above sample preparation ClassLoaderTestServlet the EAR application, we did not test during the Spring library to the WebSphere Application Server, or place the system library path in JVM, Spring libraries only exist in the applications WEB-INF/lib directory (ie: The class load range), then why are there class loader memory leak? Should not be a memory leak problem caused by the Introspector's!

By analyzing the source code that Spring, Spring Bean definitions such as class loading, such as ClassPathXmlApplicationContext parent AbstractApplicationContext used commons-logging components to carry out the logging framework, so ClassLoaderTestServlet sample tests of memory leak is caused by the commons-logging of.

So how do we avoid the commons-logging memory leak?

In fact, we can follow the above framework for the Introspector leaks Spring solution to the problem, write a Servlet container ServletContextListener to monitor the life cycle, Once WebContainer been terminated, we can take the initiative to release a static variable stored in the LogFactory class factories produce all the results are used the class instance object, the ultimate solution commons-logging memory leak.

Clear LogFactory class static variable for the factories in the instance of the object code is as follows:

view plain print?

  1. package com.test;
  2. import javax.servlet.ServletContextEvent;
  3. import javax.servlet.ServletContextListener;
  4. import org.apache.commons.logging.LogFactory;
  5. public class ApplicationLifecycleListener implements ServletContextListener (
  6. public void contextDestroyed (final ServletContextEvent sce) (
  7. LogFactory.release (Thread.currentThread (). GetContextClassLoader ());
  8. )
  9. public void contextInitialized (final ServletContextEvent sce) (
  10. )
  11. )

Of course, we must register this ServletContextListener in web.xml, web.xml sample configuration is as follows:

web.xml configuration file

view plain print?

  1. <? Xml version = "1.0" encoding = "UTF-8"?>
  2. <Web-app id = "WebApp_ID" version = "2.4"
  3. xmlns = ""
  4. xmlns: xsi = ""
  5. xsi: schemaLocation = "">
  6. <Display-name> ClassLoader </ display-name>
  7. <Context-param>
  8. <Param-name> contextConfigLocation </ param-name>
  9. <Param-value> classpath *: spring / *. xml </ param-value>
  10. </ Context-param>
  11. <! - Spring Refresh Introspector prevent memory leaks, recommend to the Listener in the first place, at least in the first Spring Related Listener ->
  12. <Listener>
  13. <Listener-class> org.springframework.web.util.IntrospectorCleanupListener </ listener-class>
  14. </ Listener>
  15. <Listener>
  16. <Listener-class> org.springframework.web.context.ContextLoaderListener </ listener-class>
  17. </ Listener>
  18. <Listener>
  19. <Listener-class> com.test.ApplicationLifecycleListener </ listener-class>
  20. </ Listener>
  21. ... ...

Through experiments, we finally solved the infamous Spring standard application class loader ClassLoader memory leak problem. !


Tomcat and Websphere class loading mechanism

JVM's garbage collection and tuning Xiangjie

With updating ClassLoader several times, jdk1.4.1_05 server VM will be down with an error java.lang.OutOfMemoryError

java.lang.OutOfMemoryError: PermGen space and their solutions

OutOfMemory error when repetatively deploying and undeploying with 10 minute interval in JBoss Application Server

How to fix the dreaded "java.lang.OutOfMemoryError: PermGen space" exception (classloader leaks)

Commons-logging Logging / UndeployMemoryLeak

Supporting the log4j RepositorySelector in Servlet Containers

commons-logging Classloader and Memory Management # Classloader and Memory Management

Big memory leak in the use of CGLIB

分类:Java 时间:2010-07-29 人气:431
blog comments powered by Disqus


  • Java program in the "memory leak" problem 2010-07-20

    Transfer from: Soar Abstract: Java's memory management system from the beginning with a discussion of the Java process memory leak cause of the problem, citing a typical memory leak prob

  • Java memory leak problem analysis 2010-03-29

    <! - Info --><!-- div> </ div> <div> <ul> <img src = " "/> <p> <a href=""> information first time </ a> </ p> </ ul> <ul&g

  • Java memory leak problem analysis (change) 2010-03-28

    People talking about memory leaks, of course, for c / c + +, this should be the long-standing problems, but many more Java staff also need to discuss this issue, I write a summary here, we want to have some reference value. Generous concept of memory

  • Dbcp database connection pool with c3p0 using 2011-08-29

    As we all know, whether it is B / S or C / S applications, and databases are inevitably have to deal with. Exchange with the database Each process, often requires a lot of connections. For a large-scale applications, often need to deal with tens of m

  • The definition of connection pool and release (reproduced) 2010-03-18

    The basic working principle of the connection pool 1. Basic concepts and principles Can be seen from the above analysis, the root of the problem lies in the inefficient management of the database connection resource . We know, for the sharing of reso

  • apache connection pool to use 2011-07-14

    apache connection pool to use commons DBCP Brief description of configuration parameters In the configuration, the main difficult to understand the main :removeAbandoned .logAbandoned.removeAbandonedTimeout.maxWait These four parameters, set rmoveAba

  • Thread pool and connection pool 2010-06-09

    The principle of the thread pool: Look at how the thread pool is about what? In fact, the principle is very simple thread pool, similar to the concept of the operating system in the buffer, its process is as follows: first, a certain number of thread

  • spring connection pool configuration Xiangjie 2010-07-24

    First, an overview of the connection pool Database Connection Pool overview: Database connection is an expensive key limited resources, this web page in a multi-user applications, especially embodied. The management of the database connection can sig

  • The principle of the thread pool and connection pool works 2011-08-18

    The principle of the thread pool : Look at how the thread pool is exactly the same thing? In fact, the principle is very simple thread pool , Similar to the operating system buffer concept, it follows the process : First start a certain number of thr

  • Java memory leak in the 2010-12-08

    1 Introduction An important advantage of Java is through the garbage collector GC (Garbage Collection) automatically manages the recovery of memory, the programmer does not need to release the memory by calling the function. Therefore, many programme

iOS 开发

Android 开发

Python 开发



PHP 开发

Ruby 开发






Javascript 开发

.NET 开发



Copyright (C), All Rights Reserved. 版权所有 闽ICP备15018612号

processed in 0.037 (s). 13 q(s)