A series of articles on this topic:
Note: Permgen (permanent generation) belongs to the concept of JDK1.7 and previous versions; in order to adapt to the development of Java programs, JDK8 and later versions use less restrictive MetaSpace instead
JVM limits the maximum memory usage of Java programs, which can be configured through startup parameters. The heap memory of Java is divided into multiple areas, as shown in the following figure:
java.lang.OutOfMemoryError: PermGen space error message means: Permanent Generation (Permanent Generation) memory area is full.
Cause Analysis
Let's first look at what PermGen is used for.
In JDK1.7 and earlier versions, permanent generation is mainly used to store class definitions loaded/cached in memory, including class names, fields, methods and bytecodes (method bytecode); and constant pool information; classes associated with object arrays/type arrays, and class information optimized by the JIT compiler.
It is easy to see that the usage of PermGen is related to the number/size of classes loaded into memory by the JVM. It can be said that the main reason for java.lang.OutOfMemoryError: PermGen space is that the number of classes loaded into the memory is too large or the size is too large.
The simplest example
We know that the usage of PermGen space has a lot to do with the number of classes loaded by the JVM. The following code demonstrates this situation:
import javassist.ClassPool;
public class MicroGenerator {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100_000_000; i++) {
generate("eu.plumbr.demo.Generated" + i);
}
}
public static Class generate(String name) throws Exception {
ClassPool pool = ClassPool.getDefault();
return pool.makeClass(name).toClass();
}
}
This code generates many classes dynamically in the for loop. As you can see, it is very simple to use the javassist tool class to generate a class.
Executing this code will generate a lot of new classes and load them into memory. As more and more classes are generated, they will fill up the Permgen space, and then throw a java.lang.OutOfMemoryError: Permgen space error, of course , Other types of OutOfMemoryError may also be thrown.
To see the effect quickly, you can add appropriate JVM startup parameters, such as: -Xmx200M -XX:MaxPermSize=16M and so on.
OutOfMemoryError during Redeploy
Note: If Tomcat generates a warning during development, you can ignore it. It is recommended not to redploy in the production environment, just close/or Kill related JVM directly, and then start from the beginning.
The following situation is more common. When redeploying a web application, it is likely to cause a java.lang.OutOfMemoryError: Permgen space error. It stands to reason that when redeploying, a container such as Tomcat will use a new classloader to load a new class. Let the garbage collector clean up the previous classloader (along with the loaded class).
But the actual situation may not be optimistic. Many third-party libraries, as well as some restricted shared resources, such as threads, JDBC drivers, and file system handles (handles), will cause the previous classloader to be unable to be completely uninstalled. Then in redeploy, The previous class still resides in PermGen, and each redeployment will generate tens of MB or even hundreds of MB of garbage.
Suppose that when an application is started, the JDBC driver is loaded through the initialization code to connect to the database. According to the JDBC specification, the driver will register itself to java.sql.DriverManager, that is, add an instance of itself to a static in DriverManager area.
Then, when the application is uninstalled from the container, java.sql.DriverManager still holds a JDBC instance (Tomcat often warns), and the JDBC driver instance holds a java.lang.Classloader instance, so the garbage collector has no way. Reclaim the corresponding memory space.
The java.lang.ClassLoader instance holds all the loaded classes, usually tens/hundreds of MB of memory. As you can see, redeploy will take up another piece of PermGen space of the same size. After multiple redeploys, it will cause java.lang.OutOfMemoryError: PermGen space error. In the log file, you should see related error messages.
solution
1. Solve the OutOfMemoryError generated when the program starts
When the program starts, if PermGen is exhausted and an OutOfMemoryError is generated, it is easy to solve. Increase the size of PermGen so that the program has more memory to load the class. Modify the -XX:MaxPermSize startup parameter, similar to the following:
java -XX:MaxPermSize=512m com.yourcompany.YourClass
0 comments:
Post a Comment