OutOfMemoryError系列(3): Permgen space
https://blog.csdn.net/renfufei/article/details/77994177
Description: Permgen (permanent generation) belongs to the concept and previous versions of JDK1.7; to adapt to the development of Java programs, JDK8 later version uses less restrictive MetaSpace instead, please refer to the next article: OutOfMemoryError series (4) : Metaspace .
This is the third article in this series, a list of related articles:
- OutOfMemoryError系列(1): Java heap space
- OutOfMemoryError系列(2): GC overhead limit exceeded
- OutOfMemoryError系列(3): Permgen space
- OutOfMemoryError系列(4): Metaspace
JVM limits the maximum memory usage Java program can be configured by the startup parameters. The Java heap memory is divided into a plurality of regions, as shown below:
Maximum of these areas, by the JVM startup parameters -Xmx
and -XX:MaxPermSize
specified. If not specified, it is determined according to the operating system platform and the size of physical memory.
java.lang.OutOfMemoryError: PermGen space meaning expressed error message is: substituting permanent (Permanent Generation) memory area is full
Cause Analysis
Let's take a look at PermGen is used to doing.
In JDK1.7 and earlier, permanent substituting (permanent generation) it is mainly used for storing load / cache memory to class definitions, including the class name (name), field (Fields), methods (methods) and bytecode (method bytecode); and the constant pool (constant pool information); class object array (object arrays) / array type (type arrays) associated, as well as the JIT compiler optimization class information.
It is easy to see, and the amount of PermGen JVM class is loaded into memory amount / size. It can be said java.lang.OutOfMemoryError: PermGen space The main reason is the number of class loaded into memory volume too much or too large.
Examples
The simplest example
We know that the use of PermGen space, have a great relationship with the number of class JVM loaded. The following code demonstrates this:
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(); } }
The code in the for loop, a lot of dynamically generated class. It can be seen using javassist tools generate a class is very simple.
Execute this code will generate a lot of new class and load it into memory, as more and more generated class, will fill Permgen space, then throws java.lang.OutOfMemoryError: Permgen space error, of course, , there may be other types of throws OutOfMemoryError.
To quickly see the effect, you can add the appropriate JVM startup parameters, such as: -Xmx200M -XX:MaxPermSize=16M
and so on.
Generated when OutOfMemoryError Redeploy
Note: If a warning in the development of Tomcat, can be ignored. Production environment is not recommended redploy, directly off / or Kill relevant JVM, then you can start from scratch.
The following scenario is more common when redeploy web applications, it may cause java.lang.OutOfMemoryError: PermGen Space . Error stands to reason that, when redeploy, Tomcat containers would like to use the new classloader to load the new class, let the garbage collector will before classloader (along with the loaded class together) clean out.
But the reality may not be optimistic, many third-party libraries, and some limited sharing of resources, such as thread, JDBC drivers, and the file system handles (handles), will lead classloader can not be completely uninstalled before. So when redeploy, before the class still reside in the PermGen, each will have to re-deploy MB dozens, even hundreds of MB of garbage.
Suppose an application startup, drivingly connected through the load JDBC database initialization code. JDBC spec driver will register itself with the java.sql.DriverManager , which is itself an instance (instance) is added to DriverManager a static in area.
So, when the application is unloaded from the container, java.sql.DriverManager still holds JDBC Examples (Tomcat often warn), while another instance of the JDBC driver holds java.lang.Classloader instance, the garbage collector is also no way to recovering the corresponding memory space.
The java.lang.ClassLoader examples of all class holds its load, usually tens / hundreds of MB of memory. We can see, it will take up another piece about the size of PermGen space redeploy, after several redeploy, it will cause java.lang.OutOfMemoryError: PermGen space errors in the log file, you should see the associated error message.
solution
1. resolve OutOfMemoryError generated when the program starts
When the program starts, if an error is generated OutOfMemoryError PermGen exhausted, it is very easy to solve PermGen increase the size of the program to have more memory to load the class can be modified.. -XX: MaxPermSize startup parameters, like the following:
java -XX:MaxPermSize=512m com.yourcompany.YourClass
The maximum configuration allows more space for the JVM to use PermGen 512MB
, if not enough, will throw OutOfMemoryError .
2. OutOfMemoryError generated solve redeploy
We can heap dump analysis (heap dump analysis) - After redeploy, execute the dump heap, like the following:
jmap -dump:format=b,file=dump.hprof <process-id>
Then load the file obtained by the dump heap dump analyzer (e.g. powerful Eclipse MAT). Find duplicate class, especially the class loader (classloader) corresponding class. You may want to compare all the classloader, to find out that currently in use.
Eclipse MAT on each platform has its own installation package is about is about 50MB, download the official website address:. Http://www.eclipse.org/mat/downloads.php
For the class loader is not used (inactive classloader), you need to determine the shortest path to the GC root , to see which prevent it from being garbage collector recovered. In order to find the root of the problem. If the cause is a third-party library, you can search Google / StackOverflow to find a solution. If the problem is your own code, you need at the right time to release the relevant reference.
3. resolve OutOfMemoryError generated runtime
If OutOfMemoryError occurs during operation, it first needs to confirm whether GC unloaded from PermGen class . The official JVM in this area is quite conservative (after loading the class, has been allowed to reside in memory, even if the class is no longer used). However, modern applications during operation, dynamically creates a lot of the class, which class is basically very short life cycle, the old version of the JVM can not deal with them very well. Then we need to allow the JVM to uninstall class. Use the following startup parameters:
-XX:+CMSClassUnloadingEnabled
By default CMSClassUnloadingEnabled value false
, so it is necessary to explicitly specify. When enabled, GC will clean up PermGen, uninstall unwanted class. Of course, this option is only set UseConcMarkSweepGC take effect. If the ParallelGC , or Serial GC when you need to switch to the CMS :
-XX:+UseConcMarkSweepGC
If it is determined class can be uninstalled, if there OutOfMemoryError, it would need a heap dump analysis, which is similar to the following command:
jmap -dump:file=dump.hprof,format=b <process-id>
Then load the heap dump heap dump by the analyzer (e.g., Eclipse MAT). ClassLoader find the heaviest, is that the most loaded class number by the number of instances of the class and the corresponding load, than the class loader to identify the most forward part, analyzed one by one.
For each class suspected, to the need to manually track the generated class code, to locate the problem.
Further reading: with OOM: Permgen say goodbye
Original link: https://plumbr.eu/outofmemoryerror/permgen-space
Translation Date: August 28, 2017
Translators: anchor: http://blog.csdn.net/renfufei