Dealing with “java.lang.OutOfMemoryError: PermGen space” Error – 处理 “java.lang.OutOfMemoryError:PermGen space” 错误

最后修改: 2022年 10月 8日

1. Overview


PermGen (Permanent Generation) is a peculiar piece of memory allocated for running JVM-based applications. PermGen error is one from the java.lang.OutOfMemoryError family, and it’s an indication of a resource (memory) exhaustion.


In this quick tutorial, we’ll look at what causes the java.lang.OutOfMemoryError: Permgen space error and how it can be solved.

在这个快速教程中,我们将了解导致java.lang.OutOfMemoryError:Permgen space错误以及如何解决这个问题。

2. Java Memory Types


The JVM works with two types of memory: the stack and the heap. The stack is used only to store primitive types and object addresses. The heap instead contains the value of the objects. When we talk about memory errors, we always refer to the heap. PermGen is, in fact, part of the heap memory but is separated and handled differently from the main memory of the JVM. The most important concept to grasp is that it is possible to have a lot of available space remaining in a heap and still running out of perm gen memory.

JVM使用两种类型的内存工作:堆栈和。堆栈仅用于存储原始类型和对象地址。而堆则包含了对象的值。当我们谈论内存错误时,我们总是提到堆。事实上,PermGen是堆内存的一部分,但它与JVM的主内存分开并以不同的方式处理。需要掌握的最重要的概念是,有可能在堆中剩余大量的可用空间,但仍然耗尽perm gen内存。

The principal scope of the PermGen is to store the static content of a Java Application Runtime: in particular, among other things, it contains static methods, static variables, references to static objects, and class files.


3. java.lang.OutOfMemoryError: PermGen。PermGen

Simply put, this error occurs when the space allocated for the PermGen is no longer capable of storing objects. This happens because PermGen is not dynamically allocated and has a fixed maximum capability. The default size is 82 Mb for 64-bit version JVM and 64 Mb for old 32-bit JVM.


One of the most frequent reasons for the exhaustion of the PemGen is memory leaks related to classloaders. In fact, PermGen contains class files, and classloaders are responsible for loading Java Classes. Classloader issues are frequent in application servers where multiple classloaders are instantiated to achieve the independent deployment of various applications.

PemGen耗尽的最常见原因之一是与classloaders有关的内存泄漏。事实上,PermGen包含类文件,而classloaders负责加载Java Classes。类加载器问题在应用服务器中经常出现,在这些服务器中,多个类加载器被实例化以实现各种应用的独立部署。

Problems arise when an application gets undeployed, and the server container keeps a reference of one or more classes. If this happens, the class loader itself cannot be garbage collected, thus saturating the PermGen memory with his class files. Another common reason for PermGen breakdown is application threads that continue to run after an application gets undeployed, thus maintaining several objects allocated in memory.


4. Dealing with the Error


4.1. Tune the Right JVM parameters


The first thing to do regarding limited memory spaces is to increase that space if possible. By using specific flags, the default size of the PermGen space can be increased. Big applications with thousands of classes or a huge number of Java Strings usually need a bigger PermGen space. By using the JVM parameterXX:MaxPermSize is possible to specify a bigger space to allocate for this memory area. 


Since we mentioned JVM flags, It’s also worth mentioning a not-so-used flag that can trigger this error. The –Xnoclassgc JVM parameter, when specified at the start of the JVM, explicitly removes class files from the list of entities to be trashed. In application servers and with modern frameworks that load and unload classes thousands of times per application’s lifecycle, this can bring to very fast exhaustion of the PermGen space.


In older versions of Java, classes are a permanent part of the heap, meaning that once loaded, they remain in memory. By specifying the CMSClassUnloadingEnabled (for Java 1.5 or CMSPermGenSweepingEnabled for Java 1.6) JVM Parameter, it is possible to enable the garbage collection of classes. If we happen to be working with Java 1.6, UseConcMarkSweepGC must also be set to true. Otherwise, the CMSClassUnloadingEnabled argument would be ignored. 

在旧版本的Java中,类是堆的永久组成部分,这意味着一旦加载,它们就会留在内存中。通过指定CMSClassUnloadingEnabled(针对Java 1.5或CMSPermGenSweepingEnabled针对Java 1.6)JVM参数,可以启用类的垃圾收集。如果我们碰巧使用的是Java 1.6,UseConcMarkSweepGC也必须被设置为true。否则,CMSClassUnloadingEnabled参数将被忽略。

4.2. Upgrading to JVM 8+

4.2.升级到JVM 8+

Another way of fixing this kind of error is by upgrading to a newer version of Java. Starting with Java version 8, Permgen has been entirely replaced by Metaspace, which has an automatically resizable space and an advanced feature that enables the cleaning of dead classes. 


4.3. Heap Analysis


It should be trivial noticing that in case of a memory leak, none of the solutions provided can suffice. Memory will finish, no matter how great the size. Even Metaspace has a limited amount of memory available. Deep HEAP analysis is sometimes the only solution and can be conducted with tools like VisualGC or JPROFILER.


5. Summary


In this quick write-up, we have seen the purpose of PermGen memory and the main difference with heap memory. Next, we have seen what the java.lang.OutOfMemoryError: Permgen error means and in what peculiar cases gets triggered. In the last section, we focused on the various solutions we can put into play when trying to solve this peculiar problem.