分析java.lang.OutOfMemoryError: PermGen space

    SUN JDK+Tomcat 5.5.20运行服务的时候遇到问题,服务器跑几天后就会挂掉,并报java.lang.OutOfMemoryError: PermGen space异常。

    发现很多人把问题归因于: spring,hibernate,tomcat,因为他们动态产生类,导致JVM中的permanent heap溢出 。

   然后解决方法众说纷纭,有人说升级 tomcat版本到最新甚至干脆不用tomcat。还有人怀疑spring的问题,在spring论坛上讨论很激烈,因为spring在AOP时使用CBLIB会动态产生很多类。

    有人对更基础的JVM做了检查,发现了问题的关键。原来SUN 的JVM把内存分了不同的区,其中一个就是permenter区用来存放用得非常多的类和类描述。本来SUN设计的时候认为这个区域在JVM启动的时候就固定了,但他没有想到现在动态会用得这么广泛。而且这个区域有特殊的垃圾收回机制,现在的问题是动态加载类到这个区域后,gc根本没办法回收!2003年的时候就有一个bug报告给sun,但是到现在,这个bug还没有close!有人在这个bug加了句评语:“A bug this critical is open since 2003? Absolutely shameful.” (一个关键的BUG2003年就提了,真可耻) ,对这个bug最彻底的解决办法就是不要用SUN的JDK,而改用BEA的 JRokit.
引用
单纯 “spring在AOP时使用CBLIB会动态产生很多类” 不至于对Perm空间产生威胁。因为这些代理产生的类也是常量数目:即每个类只会产生一个代理类,不会每次调用都产生新的代理类。把Perm开大点吧,应该就不会有问题 .

请参考jvm启动参数: PermSize, MaxPermSize 。平常 在我的Eclipse启动中,我不仅仅调整-Xms, -Xmx;  PermSize, MaxPermSize 也是我调整的一部分。因为如果你启动过多项目,可能Perm空间就很吃力, 这点可以通过jvm命令观察。服务器更少不了这些参数的调整。

引用
如果还是用ejb2的话,类就更多,而permsize默认就4m,怎么够用,加大了就好。

引用
jvm里的相关描述:
方法区的大小不必是固定的,虚拟机可以根据应用的需要动态调整。同样,方法区也不必是连续的,方法区可以在一个堆(甚至是虚拟机自己的堆)中自由分配。另外,虚拟机也可以允许用户或者程序员指定方法区的初始大小以及最小和最大尺寸等

引用
java.lang.OutOfMemoryError: PermGen space主要是字节码增强类大量充斥了方法区,而且不能被sun的jvm回收造成的。

引用
一般GC算法也是会照顾permanent generation的,每次permanent generation满了要做扩展前都会触发一次FULL GC,除非设置了-Xnoclassgc。

引用
使用JRockit可以规避这个问题不是因为JRockit的GC有什么特别,而是JRockit里没有permanent generation这个概念,所以就不存在permanent generation memory leak的问题。

引用
OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。

改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

引用
其实不能说是SUN的设计缺陷吧,permanent SPACE大小不是可以调的吗,JSP应用容易产生这个问题,我们用SWING客户端,很少碰到这个问题。

引用
一个应用(jvm)中类的个数应该小于某个常量,像创建对象一样频繁的创建类不出问题才怪。


猜你喜欢

转载自wentao365.iteye.com/blog/1161488