java.lang.OutOfMemoryError:PermGen space 原因详解,,很可能大多数java开发
java.lang.OutOfMemoryError:PermGen space 原因详解,,很可能大多数java开发
很可能大多数java开发人员都遇到过OutOfMemory error。然而java的内存溢出也有不同。最常见的是“Exception in thread "main" java.lang.OutOfMemoryError:java heap space”, 这个异常信息表示jvm内存堆用尽了,超出了jvm的启动参数-Xmx中设置的值。 内存溢出错误不只这一种。
另外一种内存溢出错误的提示消息是:“java.lang.OutOfMemoryError: PermGen space”. 多数内存优化工具无法检测到这个错误。所以这个错误更麻烦,也更有趣。
要理解并修复这个错误,我们要理解,处于对垃圾回收性能优化的目的,java的内存堆分为不同的代,在不同内存段中存储的对象的年龄不一样的,而对于每一代垃圾回收的算法也是不一样的。对象分配时会在Young generation上,这是因为多数对象都会在这一个代上消失。当这一代所占用的内存填满之后,会触发一次这一代内存回收。假如刚分配的对象更容易死亡,那么这一代上的回收也就最频繁。而在回收之后依然存活的对象会移动到Tenured Generation。对Tenured Generation的回收需要涉及到所有的存活的对象。每一代包含存活时间不同的对象,每一代的回收策略也不一样。
另外还有第三代:Permanent Generation即持久代。持久代中要保存用户定义类的meta信息。如果程序中定义了很多类,就有可能很快填满这一代的内存空间,从而导致java.lang.OutOfMemoryError:PermGen. 这一代的内存空间和-Xmx参数没有关系,也和程序所在机器上的剩余内存有多少没有关系。
Sun的jvm允许你设定不同代的内存大小,也包括持久代上的内存。XX:PermSize=64m设定程序启动时持久代的内存大小为64M;-XX:MaxPermSize=128m指定持久代的最大内存为128M。
如果你不设定这个参数,jvm将使用默认的配置,不同jdk版本的默认参数有所不同,如下图所示:
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 |
下面的jsp脚本可以用来监控jvm内存使用情况:
<%@ page import="java.lang.management.*" %><%@ page import="java.util.*" %><html><head> <title>JVM Memory Monitor</title></head><body><% 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><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></body></html>
用户点评