Detailed JAVA memory leak sample code
When locating JVM performance problems, you may encounter memory leakage leading to JVM OUTOFMEMORY. When using Tomcat container, if the parameter "reloadable =" true "is set, you may also encounter memory overflow when frequently hot deploying applications. Tomcat's hot deployment principle is to stop and then start the application after detecting that the files in the WEB-INF / classes or WEB-INF / lib directory have changed. Since Tomcat assigns a webappclassloader to each application by default, the principle of hot replacement is to create a new classloader to load classes, Since the uniqueness of a class in the JVM is determined by its class file and its class loader, reloading the class can achieve the purpose of hot replacement. When the number of hot deployments is large, the JVM will load more classes. If the previous classes are not unloaded in time for some reason (such as memory leakage), it may lead to permanent generation or OUTOFMEMORY of Metaspace. This article uses a demo to briefly introduce the scenario where ThreadLocal and classloader lead to memory leakage and finally OUTOFMEMORY.
Class uninstallation
After the class is used, it will be unloaded if the following conditions are met:
1. All instances of this class in the heap have been recycled, that is, there is no instance object of this class in the heap.
2. The classloader that loads this class has been recycled.
3. The class object corresponding to this class can not be referenced anywhere, and this class object cannot be accessed through reflection.
If the class meets the unloading conditions, the JVM will unload the class during GC, that is, clear the class information in the method area.
Scene introduction
In the last article, I introduced the principle of ThreadLocal. Each thread has a threadlocalmap. If the life cycle of the thread is long, the entry in threadlocalmap may not be recycled, and the ThreadLocal object has always been strongly referenced by the thread. Because the instance object will hold the reference of the class object and the class object will hold the reference of the classloader that loads it, In this way, the class cannot be unloaded. When enough classes are loaded, there may be memory overflow of permanent generation or Metaspace. If the class has large objects, such as large byte arrays, it will lead to memory overflow in the Java heap.
Source code introduction
An inner class is defined here. The inner class has a static ThreadLocal object, which is mainly used to make the thread hold the strong reference of the inner class, so that the inner class cannot be recycled. A user-defined class loader is defined to load the inner class, as shown below:
Heap memory overflow
In order to trigger the memory overflow in the heap area, I set up a byte array of 1MB in the Inner class, and call threadLocal. in the static block. Get(), only the call will trigger initialvalue() to initialize an inner object, otherwise it will just create an empty ThreadLocal object, and there is no data in threadlocalmap.
JVM parameters are as follows:
After 814 times of execution, the JVM heap memory overflowed, as shown below:
It can be seen that the JVM has no memory to create new inner objects, because many 1MB byte arrays are stored in the heap. Here I print out the histogram of the class (the following figure shows the scene with a heap size of 1024m), omitting some irrelevant classes. It can be seen that the byte array occupies 855m space and 814 com. Com. Objects are created ezlippi. The instance of memoryleak $customclassloader basically matches the size of the byte array:
Metaspace overflow
In order to overflow the Metaspace, it is necessary to reduce the space of the Metaspace and load enough classes before heap overflow. Therefore, I adjusted the following JVM parameters and adjusted the size of the byte array to 1KB, as shown below:
From the GC log, it can be seen that a fullgc will be triggered when the meraface reaches the GC threshold (that is, when the maxmetaspacesize is configured):
From the above example, we can see that improper use of class loader and ThreadLocal will indeed lead to memory leakage. The complete source code is in GitHub