[Reprint] OutOfMemoryError series (3): Permgen space

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:

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:

java.lang.outofmemoryerror: Permgen space

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

Guess you like

Origin www.cnblogs.com/jinanxiaolaohu/p/12122894.html