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):
|
<%@ page import="java.lang.management.*" %> <%@ page import="java.util.*" %> <html> <head> <title>JVM Memory Monitor</title> </head> <% Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator(); while (iter.hasNext()) { MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next(); %> <table border="0" width="100%"> <tr><td colspan="2" align="center"><h3>Memory MXBean</h3></td></tr> <tr><td width="200">Heap Memory Usage</td><td><%= ManagementFactory.getMemoryMXBean().getHeapMemoryUsage() %></td></tr> <tr><td>Non-Heap Memory Usage</td><td><%= ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage() %></td></tr></body> <tr><td colspan="2"> </td></tr> <tr><td colspan="2" align="center"><h3>Memory Pool MXBeans</h3></td></tr> <% Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator(); while (iter.hasNext()) { MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next(); %> <tr><td colspan="2"> <table border="0" width="100%" style="border: 1px #98AAB1 solid;"> <tr><td colspan="2" align="center"><b><%= item.getName() %></b></td></tr> <tr><td width="200">Type</td><td><%= item.getType() %></td></tr> <tr><td>Usage</td><td><%= item.getUsage() %></td></tr> <tr><td>Peak Usage</td><td><%= item.getPeakUsage() %></td></tr> <tr><td>Collection Usage</td><td><%= item.getCollectionUsage() %></td></tr> </table> </td></tr> <tr><td colspan="2"> </td></tr> <% } %> </table> |
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