How Tomcat detects memory leaks

Under normal circumstances, if we restart the web application by restarting tomcat, there is no memory leak problem. However, if the web application is reloaded without restarting tomcat, it may cause memory leaks, because after reloading, some of the original memory may not be reclaimed by the GC. For example, if the web application uses JDBC, the driver will register it. Failure to unregister when the web application is stopped will result in a memory leak.

See what is causing the tomcat memory leak. This starts with hot deployment, because tomcat provides the function of restarting the web application without restarting the container to achieve hot deployment. The loader discards and re-instantiates a WebappClassLoader class loader. However, there may be a memory leak problem in this way, because ClassLoader is a complex object, so it is more likely that it cannot be recycled by GC. In addition to having a reference to the ClassLoader object, which may cause it to fail to be recycled, it may also load the metadata Data (methods, classes, fields, etc.) that have references will not be reclaimed by GC.

memory leak

As shown in the figure above, the resources of tomcat are loaded by different class loaders . Here we only look at the BootstrapClassLoader and WebappClassLoader two class loaders.

BootstrapClassLoader is responsible for loading java.sql.DriverManager of rt.jar package ,

WebappClassLoader is responsible for loading the mysql driver package in the web application ,

One of the most important steps is that the mysql driver class needs to be registered in the DriverManager , that is, DriverManager.registerDriver(new Driver()), which is automatically completed by the mysql driver package. In this way, when the web application is hot-deployed, if the mysql Driver is not deregistered from the DriverManager, the entire WebappClassLoader will not be recycled, resulting in memory leaks.

Then see how tomcat monitors this memory leak. To judge whether WebappClassLoader will cause memory leaks, you only need to judge whether WebappClassLoader has been recycled by GC .

There is a kind of reference in Java called weak reference , which can well determine whether WebappClassLoader has been recycled by GC.

Objects associated with weak references can only survive until the next garbage collection occurs,

That is, if a WebappClassLoader object is only associated with a weak reference, it will be recycled in the next garbage collection,

But if the WebappClassLoader object is strongly referenced by other objects in addition to being associated with weak references, then the WebappClassLoader object will not be recycled.

According to these conditions, you can judge whether there is a WebappClassLoader memory leak.

The implementation of Tomcat is to achieve weak reference through WeakHashMap, just put the WebappClassLoader object into WeakHashMap ,

For example weakMap.put("a", webappClassLoader), when the webappClassLoader and its contained elements are not referenced by elements in any other class loaders, the JVM will recycle the webappClassLoader object when garbage collection occurs.

The simple implementation code is roughly as follows:

public class MemoryLeakTest{
private Map<ClassLoader, String> childClassLoaders = new WeakHashMap<ClassLoader, String>();
public String[] findReloadedContextMemoryLeaks() {
        System.gc();
        List<String> result = new ArrayList<String>();
        for (Map.Entry<ClassLoader, String> entry : childClassLoaders.entrySet()) {
            ClassLoader cl = entry.getKey();
            if (!((WebappClassLoader) cl).isStarted()) {
                result.add(entry.getValue());
            }
        }
        return result.toArray(new String[result.size()]);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

A WeakHashMap is used to track WebappClassLoader . Before finding memory leaks, System.gc() will be called forcibly; a garbage collection will be performed to ensure that all WebappClassLoaders without problems are recycled. The ones that are started are all started, and those that are closed are not started), the WebappClassLoader that has not been garbage collected is a memory leak.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325624738&siteId=291194637