Explaining java.lang.OutOfMemoryError: PermGen space

Most probably, a lot of Java developers have seen OutOfMemory error one time or other. However these errors come in different forms and shapes. The more common is: "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space" and indicates that the Heap utilization has exceeded the value set by -Xmx. This is not the only error message, of this type, however.

One more interesting flavor of the same error message, less common but hence even more troublesome is: "java.lang.OutOfMemoryError: PermGen space". Most of the memory profiler tools are unable to detect this problem, so it is
even more troublesome and therefor - interesting.

To understand this error message and fix it, we have to remember that, for optimized, more efficient garbage-collecting Java Heap is managed in generations - memory segments holding objects of different ages. Garbage collection algorithms in each generation are different. Objects are allocated in a generation for younger objects - the Young Generation, and because of infant mortality most objects die there. When the young generation fills up it causes a Minor Collection. Assuming high infant mortality, minor collections are garbage-collected frequently. Some surviving objects are moved to a Tenured Generation. When the Tenured Generation needs to be collected there is a Major Collection that is often much slower because it involves all live objects. Each generation contains variables of different length of life and different GC policies are applied to them.

There is a third generation too - Permanent Generation. The permanent generation is special because it holds meta-data describing user classes (classes that are not part of the Java language). Examples of such meta-data are objects describing
classes and methods and they are stored in the Permanent Generation. Applications with large code-base can quickly fill up this segment of the heap which will cause java.lang.OutOfMemoryError: PermGen no matter how high your -Xmx and how much memory you have on the machine.

Sun JVMs allow you to resize the different generations of the heap, including the permanent generation. On a Sun JVM (1.3.1 and above) you can configure the initial permanent generation size and the maximum permanent generation size.

To set a new initial size on Sun JVM use the -XX:PermSize=64m option when starting the virtual machine. To set the maximum permanent generation size use -XX:MaxPermSize=128m option. If you set the initial size and maximum size to equal values you may be able to avoid some full garbage collections that may occur if/when the permanent generation needs to be resized. The default values differ from among different versions but for Sun JVMs upper limit is typically 64MB.

Some of the default values for Sun JVMs are listed below.

JDK 1.3.1_06 Initial Size Maximum Size
Client JVM 1MB 32MB
Server JVM 1MB 64MB

JDK 1.4.1_01 Initial Size Maximum Size
Client JVM 4MB 64MB
Server JVM 4MB 64MB

JDK 1.4.2 Initial Size Maximum Size
Client JVM 4MB 64MB
Server JVM 16MB 64MB

JDK 1.5.0 Initial Size Maximum Size
Client JVM 8MB 64MB
Server JVM 16MB 64MB



Following is a JSP code you can use to monitor memory utilization in different generations (including PermGen):



As of JBoss v3.2.8/4.0.2, the ServerInfo MBean registered under the name
jboss.system:type=ServerInfo has been enhanced with a new operation
listMemoryPools(boolean fancy) that presents information about the
memory pools managed by the JVM.

Thank you for valuable

Thank you for valuable information.
It is very useful to me in my project.
JSP Page is very good.

Thank you , I search the web

Thank you , I search the web quite a lot for this topic and your explanation was the most usefull one

Thanks

Thanks for the code, however there was an error.

Here is the correct code:

<%@ page import="java.lang.management.*" %>
<%@ page import="java.util.*" %>

JVM Memory Monitor

<%
Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator();

while (iter.hasNext())
{
MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next();
%>

Memory MXBean
Heap Memory Usage<%=
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
%>
Non-Heap Memory
Usage<%=
ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()
%>
<%} %>
 
Memory Pool MXBeans
<%
iter = ManagementFactory.getMemoryPoolMXBeans().iterator();
while (iter.hasNext())
{
MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next();
%>

<%= item.getName() %>
Type<%= item.getType() %>
Usage<%= item.getUsage() %>
Peak Usage<%= item.getPeakUsage() %>
Collection Usage<%= item.getCollectionUsage() %>

 
<%
}

%>

another implementation

Thanks for the article! If your a JSP-XML syntax junkie like me, here's another implementation of the memory monitor page:

<jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
  >

  <jsp:directive.page contentType="text/html" />
  <jsp:directive.page import="java.lang.management.*"/>
  <jsp:directive.page import="java.util.*"/>


<html>
  <head>
    <title>JVM Memory Monitor</title>
    <style type="text/css">
      td {
        text-align: right;
      }
    </style>
  </head>
<body>
  <jsp:scriptlet>
    MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
    pageContext.setAttribute("memoryBean", memoryBean);
  
    List<MemoryPoolMXBean> poolBeans = ManagementFactory.getMemoryPoolMXBeans();
    pageContext.setAttribute("poolBeans", poolBeans);
  </jsp:scriptlet>

  <h3>Total Memory</h3>
  <table border="1" width="100%">
    <tr>
      <th>usage</th>
      <th>init</th>
      <th>used</th>
      <th>committed</th>
      <th>max</th>
    </tr>
    <tr>
      <td style="text-align: left">Heap Memory Usage</td>
      <td><fmt:formatNumber value="${memoryBean.heapMemoryUsage.init / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      <td><fmt:formatNumber value="${memoryBean.heapMemoryUsage.used / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      <td><fmt:formatNumber value="${memoryBean.heapMemoryUsage.committed / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      <td><fmt:formatNumber value="${memoryBean.heapMemoryUsage.max / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
    </tr>
    <tr>
      <td style="text-align: left">Non-heap Memory Usage</td>
      <td><fmt:formatNumber value="${memoryBean.nonHeapMemoryUsage.init / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      <td><fmt:formatNumber value="${memoryBean.nonHeapMemoryUsage.used / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      <td><fmt:formatNumber value="${memoryBean.nonHeapMemoryUsage.committed / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      <td><fmt:formatNumber value="${memoryBean.nonHeapMemoryUsage.max / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
    </tr>
  </table>

  <h3>Memory Pools</h3>
  <table border="1" width="100%">
    <tr>
      <th>name</th>
      <th>usage</th>
      <th>init</th>
      <th>used</th>
      <th>committed</th>
      <th>max</th>
    </tr>
    <c:forEach var="bean" items="${poolBeans}">
      <tr>
        <td style="text-align: left">${bean.name}</td>
        <td style="text-align: left">Memory Usage</td>
        <td><fmt:formatNumber value="${bean.usage.init / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
        <td><fmt:formatNumber value="${bean.usage.used / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
        <td><fmt:formatNumber value="${bean.usage.committed / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
        <td><fmt:formatNumber value="${bean.usage.max / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      </tr>
      <tr>
        <td></td>
        <td style="text-align: left">Peak Usage</td>
        <td><fmt:formatNumber value="${bean.peakUsage.init / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
        <td><fmt:formatNumber value="${bean.peakUsage.used / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
        <td><fmt:formatNumber value="${bean.peakUsage.committed / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
        <td><fmt:formatNumber value="${bean.peakUsage.max / (1024 * 1024)}" maxFractionDigits="1"/> Mb</td>
      </tr>
    </c:forEach>
  </table>

</body>
</html>

-paul

Hi I tried to use your code,

Hi I tried to use your code, but there is an error:

The element type "MemoryPoolMXBean" must be terminated by the matching end-tag "".

Syntax error

There's a syntax error in this code. Code inside <jsp:scriptlet> must have < and > escaped, such as in: List&lt;MemoryPoolMXBean&gt. Also at the end you need a closing tag </jsp:root>,

Finally, as this is using JSTL, you will want to deploy this inside a Web App that has agood web.xml Deployment descriptor such as

<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4"
>
<welcome-file-list>
<welcome-file>index.jsp
</welcome-file-list>
</web-app>

and make sure that JSTL is deployed / available in the container. For WebLogic 10.3.3 where I tried this on, this means deploying "C:\bea10.3.3\wlserver_10.3\common\deployable-libraries\jstl-1.2.war" as a library, then referencing this in WEB-INF/weblogic.xml as in

<?xml version='1.0' encoding='UTF-8'?>
<weblogic-web-app
xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
>
<library-ref>
<library-name>jstl
<specification-version>1.2
<implementation-version>1.2
<exact-match>false
</library-ref>

</weblogic-web-app>

Then the page shows up. Maybe there's an easier way, but above works for me. Thought i'd share this back.

Thank you for good

Thank you for good explanation and write-up. Although I am naive in this area, I was able to understand
this java.lang.OutOfMemoryError: PermGen space error.

Hey, thanks for your useful

Hey, thanks for your useful post.

Good explaination in very few words

This is a good explaination of variuos generations in few words. This is really helpful. Thanks for putting it here.

PermGen space

Hi folks,

This JSP page is awesome. However, is it possible to find out what is invoking those peaks ?

It would be cool to handle those peaks and optimize our code to avoid this kind of problem.

Thanks

Charles

PermGen space

Very nice and useful article. Thank you very much.

Java profiler tools for analysing PermGen space

Very good explanation!
can you please let us know which profilers can be used to analyse OutOfMemory PermGen space issue?

Srihari Konakanchi

Thanks for your best answer

This is the best answer I have come accross.
You have provide the detail explanation.
Thanks for your answer.
Keep it up.

its a very good solution,

its a very good solution, thanks for your help.

Thanks a lot for that JSP code

Thanks a lot for that JSP code. I have been trying for 2 or 3 days to see how much JVM heap space was being used and this is the first time I have found a program that I can actually get to work.

Thanks again!

Nice Expalnation

Very minutely explained in few words --------------------appriciative

This article is extremely

This article is extremely clear and useful. Format-wise, however, I don't understand the purpose of the wide verticle grey strip along the left side of the page. It gets in the way.

Huge thanks for the useful

Huge thanks for the useful article. This error is a real pain for me for quite a long time. I though that "java.lang.OutOfMemoryError: PermGen space" is the end of the road. I mean when I was facing this error, my work was over at this point because I didn't actually know what to do and what the hell this error means. But after reading your great article everything is all right now. Thanks one more time and I will be looking forward to another great ones from you.

Sincerely,

Steven Gorrson from java software development

Thanks!

Awesome write-up. Would love an edit to include Java 1.6.

Thanks Again!

This JSP page is awesome.

This JSP page is awesome. However, is it possible to find out what is invoking those peaks ? It would be cool to handle those peaks and optimize our code to avoid this kind of problem.

Mark Taylor
Thanks

Error in Tomcat 6

I was getting the PermGen error in Tomcat 6. I add the MaxPermSize setting and have not gotten the error again. Here is the line to add to the catalina.sh file:

export JAVA_OPTS="-Xmx1024m -XX:MaxPermSize=256m"

Thanks

Adding my voice to the chorus of thanks; this was really useful and clearly written. Thanks for taking the time.

Good explanation on the

Good explanation on the point.
It was very useful to understand the things better

Thank you for sharing

cosplay

As of JBoss v3.2.8/4.0.2, the ServerInfo MBean registered under the name
jboss.system:type=ServerInfo has been enhanced with a new operation
listMemoryPools(boolean fancy) that presents information about the
memory pools managed by the JVM.

wow account for sale

Just would like thanks for special read. I have enjoy it with great interest. You must spend numerous time and effort to write. Keep up good job and definitely will stick your blog for more great posts!

Your explanations of Java

Your explanations of Java helped me a lot with writing my research paper in Computer Science.

The monitoring page

Very useful and well explained information. Here's a simple implementation of the monitoring page

<%@ page import="java.lang.management.*" %>
<%@ page import="java.util.*" %>

<h1 style="text-decoration: underline;">JVM Memory Monitor</h1>

<h2>Memory MXBean</h2>
<b>Heap Memory Usage:</b> <%= ManagementFactory.getMemoryMXBean().getHeapMemoryUsage() %><br>
<b>Non-Heap Memory Usage: </b><%= ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage() %><br>

<h2>Memory Pool MXBeans</h2>
<%
Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator();

while (iter.hasNext()) {
MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next();
%>

<div style="border-bottom: 1px solid #000000">
<b>- Name:</b> <%= item.getName() %><br>
<b>- Type:</b> <%= item.getType() %><br>
<b>- Usage:</b> <%= item.getUsage() %><br>
<b>- Peak Usage:</b> <%= item.getPeakUsage() %><br>
<b>- Collection Usage:</b> <%= item.getCollectionUsage() %><br>
</div>
<%
}
%>