Examples of Java threadlocal memory leaks _java

Source: Internet
Author: User
Tags garbage collection apache tomcat

Case and analysis

Problem background

In Tomcat, the following code is inside the WebApp, causing a WebappClassLoader leak that cannot be reclaimed.

 public class MyCounter {private int count = 0;
    public void Increment () {count++;
    public int GetCount () {return count; } public class Mythreadlocal extends threadlocal<mycounter> {} public class Leakingservlet extends HttpServlet

    {private static mythreadlocal mythreadlocal = new mythreadlocal (); protected void doget (HttpServletRequest request, httpservletresponse response) throws Servletexception, Ioexce
        ption {MyCounter counter = Mythreadlocal.get ();
            if (counter = = NULL) {counter = new MyCounter ();
        Mythreadlocal.set (counter);
                        } response.getwriter (). println ("The current thread served this servlet" + counter.getcount ()
        + "Times");
    Counter.increment (); }
}

The above code, as long as LeakingServlet it is invoked once, and the thread that executes it does not stop, it can cause a WebappClassLoader leak. Each time you reload apply, there will be more than one WebappClassLoader instance, which eventually results PermGen OutOfMemoryException .

Solve the problem

Now let's think about why the above ThreadLocal subclass causes a memory leak.

WebappClassLoader

First, we have to figure out WebappClassLoader what the hell is going on?

For WEB applications running in the Java EE container, the ClassLoader is implemented differently than a typical Java application. Different WEB containers can be implemented differently. In the case of Apache Tomcat, each WEB application has a corresponding class loader instance. The class loader also uses proxy mode, but the difference is that it first tries to load a class, if no more proxies are found to the parent class loader. This is in contrast to the order of the generic class loader. This is the recommended practice in the Java Servlet specification, which is designed to make the Web apply its own class higher precedence than the Web container-supplied class. One exception to this proxy pattern is that the Java core library class is not within the lookup range. This is also to ensure that the Java core library is type-safe.

That WebappClassLoader is, the custom class loader that Tomcat loads WebApp, each webapp ClassLoader is different, in order to isolate classes that are loaded by various applications.

So WebappClassLoader what does the feature have to do with memory leaks? Not yet, but it's a very important feature that deserves our attention: every WebApp will have its own WebappClassLoader , unlike the Java core ClassLoader.

We know that WebappClassLoader the leak must be caused by a strong reference to another object, so we can try to draw their reference graph. Wait a minute! What is the role of the ClassLoader? Why are they strongly referenced?

Life cycle of classes and ClassLoader

To solve the problem above, we have to look at the life cycle of the class and the relationship of the ClassLoader.

The main related to our case is the uninstall of the class:

After the class has been used, the class is unloaded if the following conditions are true:

1, all instances of the class have been reclaimed, that is, no instances of the class exist in the Java heap.

2, loading the class ClassLoader has been recycled.

3. The corresponding object of the class is java.lang.Class not referenced anywhere, and there is no way to access the class by reflection anywhere.

If all three of these conditions are met, the JVM will unload the class when garbage collection in the method area, and the class unload process is to empty the class information in the method area, and the entire lifecycle of the Java class is over.

Classes loaded by the class loader brought by the Java virtual machine are never unloaded during the life cycle of the virtual machine. The Java Virtual machine's own class loader includes the root class loader, the extended class loader, and the System class loader. These class loaders are always referenced by the Java Virtual machine itself, and these class loaders always refer to the class objects of the classes they load, so these class objects are always accessible.

Classes loaded by the user-defined ClassLoader can be unloaded.

Note that the above remark, WebappClassLoader if leaked, means that the classes it loads cannot be unloaded, which explains why the above code causes PermGen OutOfMemoryException .

The key point looks at the picture below

we can see that the class loader object is doubly associated with the class object it loads. This means that the Class object may be a strong reference WebappClassLoader , causing it to leak.

referencing graphs

After understanding the relationship between the ClassLoader and the life cycle of the class, we can begin to draw a reference graph. (in the picture LeakingServlet.class and the myThreadLocal reference painting is not rigorous, mainly to express the myThreadLocal meaning of the class variable)

Below, we analyze the cause of the leak according to the above diagram WebappClassLoader .

1, LeakingServlet holding static MyThreadLocal , resulting myThreadLocal in a life cycle LeakingServlet as long as the class life cycle. This means that myThreadLocal it will not be recycled, and weak references are useless, so when the frontline fails to pass ThreadLocalMap the protective measures to clear counter strong references.

2, strong reference chain: thread -> threadLocalMap -> counter -> MyCounter.class -> WebappClassLocader , leading to WebappClassLoader leakage.

Summarize

Memory leaks are difficult to spot and are often caused by multiple causes. Threadlocal because of its thread-bound lifecycle as a frequent memory leak, a bit of carelessness breeds catastrophe. This article is only an analysis of a particular case, if it can be extrapolate, that is excellent. I hope this article can be helpful to everyone.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.