`
gladto
  • 浏览: 78586 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

OutOfMemory:PermGen Space异常的处理和分析&myeclipse tomcat内存溢出解决方法[转]

    博客分类:
  • Java
阅读更多

Java程序员没有遇到过OutOfMemory简直就是不可能的事情!

可见在Java的世界中,太多的不确定因素导致Java运行程序直接崩溃,直接抛出OutOfMemory异常,而一旦遇到了这个问题,调查起来就非常的困难。在JDK 5.0以前,OutOfMemory只有这么一句话: java.lang.OutOfMemory Exception…基本上无从下手,无从分析。从JDK 5.0以后对OutOfMemory增加了许多的详细说明,为这个异常的分析提供了很大的便利。

这次遇到的问题就是会抛出OutOfMemory:PermGen Space的异常,这个异常非常有意思,根据【此文章】的描述,这是一个Sun JVM的bug,从2003年开始,一只到现在都没有解决。而且提出来的解决方案是使用JRockit。Bug产生的原因已经找到,就是因为JVM在分配PermGen Space的时候出现了PermGen Space不足的情况,默认情况下 PermGen的大小为64M,在不换用JRockit的情况下,可以在启动JVM的时候添加一个参数: -XX: MaxPermSize= 128m| 256m| 512m。

那么究竟什么是PermGen呢?

PermGen 原来是指Permanent Generation,本身是在Java的垃圾收集机制(GC)中产生的一个概念。Java的垃圾收集机制最早只是遍历所有的对象,如果发现某个对象没有被引用,则回收,这是在早期的Java 1.0和Java 1.1的时候的GC规则。慢慢的,这样一种“愚蠢的”GC算法成为了JVM性能的瓶颈,在拥有大量数据的Java应用程序中,GC的算法被高度强化,于是各种各样高效的JVM GC算法被发展了起来。从J2SE也就是Java 1.2开始,JVM引入了多种GC算法,其中一种用的非常多的就是Generational Collection,中文也叫做“分代收集法”。

分代收集法摈弃了对所有对象的遍历,而是采用一些经验属性去避免额外的工作(While naive garbage collection examines every live object in the heap, generational collection exploits several empirically observed properties of most applications to avoid extra work)。其中导入了一个非常关键的概念:infant mortality (幼儿死亡率),这表示越是新生成的变量或者对象,越容易被收集。下面一张图表示了对象的生命周期,横轴表示的是测试到对象的生命周期,纵轴表示在一个指定的生命周期上被回收的对象数量。

Histogram of lifetime

可以看到,在使用了分代收集法以后,年轻一代的对象被收集的比例最高。并且在内存中的对象会按照不同的“年龄”来划分,当一个年龄段的对象满了以后,在这个年龄段上就会发生垃圾收集,从最年轻的一代开始,一直到“永生代”,在内存中,所有的对象可以划分为很多代,最后的一代“永生代”就是“Permanent Generation”,这里就是直接引出“Permanent Generation”概念的地方。具体可以参考下图:

根据前面所说的情况,在分代垃圾收集的情况下会产生Permanent Generation的概念,而这个分代垃圾收集法是并行收集和并发收集的基础,所以Permanent Generation会一直存在,那么这个Permanent Generation究竟是做什么用的呢?这里保存了JVM中所有对象的类信息,包括类的元数据,还有方法描述等等,所以这一代内存垃圾收集算法是不一样的,在Java大程序的情况下,尤其是J2EE 或者说Java EE的大型应用程序上,Permanent Generation的大小会直接限定能载入类的数量和大小。

【解决办法】就是设定JVM启动的时候参数,可以如下设置:

java -XX: PermSize=64m -XX: MaxPermSize=128m

另外PermSize 和MaxPermSize如果设置为相同还可以在一定程度上提高性能,因为,PermSize在不断的变化中会需要转移其中的数据。如果固定了以后,则可以减少每次扩大PermSize带来的性能损失。

更多的请参考 【Java官方站点】

另外,还可以在Java启动的时候添加下面的参数来看GC的运行情况:

Java -verbosegc

Tomcat直接启动正常,通过myeclipse启动tomcat内存溢出.
MyEclipse启动Tomcat无视catalina.bat中设置内存大小的问题。
在 tomcat的catalina.bat中设置set JAVA_OPTS=-Xms128m -Xmx256m,直接使用startup.bat启动tomcat没有问题。
但是在myeclipse中配置tomcat后,通过myeclipse启动就出现内存溢出,之前在catalina.bat中设置的内存似乎没有作用。

           则需要做如下设置即可解决:

           MyEclipse --> Window --> Preference... --> MyEclipse --> Application Servers -->

           Tomcat --> Tomcat 6.X --> JDK --> Optional Java VM arguments :进行设置

           设置的内容:-Xms256m -Xmx512m
                       -Dcom.sun.management.jmxremote=true

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics