Eclipse 报告内存不足和 PermSize space 错误, Eclipse 死掉的解决办法
这一段时间, Eclipse 总是死掉,几乎是稍微操作快一点就会死掉,几分钟一次,搞得人郁闷至极。浪费了不少时间,在网上搜了下,看到很多朋友也出现类似的情况,在网上求救,但是网上的办法都只是说通过修改 eclipse.ini 文件来加大 Eclipse 的内存。
自己试了下,发现不管用。今天,又死掉了,不过爆出一个经常出现的错误,大意是: permgen space 导致内存溢出。实在忍无可忍,上网一搜,发现网络真是个好东西,尤其是对我们这种自学者而言,无疑是授业解惑的良师益友。
这里总结一下自己的经验和网友的经验,希望能够对受此问题折磨的朋友有所参考价值。
解决办法如下:
在 eclipse.ini 配置文件中加上以下两行 -XX:PermSize=128M -XX:MaxPermSize=128M
加上上 2 行后,我的 eclipse.ini 文件如下所示:
-showsplash org.eclipse.platform --launcher.XXMaxPermSize 512m -vmargs -Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=128M
这里的内存大小根据自己的物理内存情况来决定吧。
从网上的资料看 PermSize 大一点肯定更好,而且最好是设置 PermSize 和 MaxPermSize 一样大。理由如下: PermSize 和 MaxPermSize 如果设置为相同还可以在一定程度上提高性能,因为, PermSize 在不断的变化中会需要转移其中的数据。如果固定了以后,则可以减少每次扩大 PermSize 带来的性能损失。
1 、 PermGen space 简介
PermGen space 的全称是 Permanent Generation space ,是指内存的永久保存区域 OutOfMemoryError: PermGen space 从表面上看就是内存益出,解决方法也一定是加大内存。
说说为什么会内存益出: ( 1 )这一部分用于 存放 Class 和 Meta 的信息 , Class 在被 Load 的时候被放入 PermGen space 区域,它和和存放 Instance 的 Heap 区域不同。 ( 2 ) GC(Garbage Collection) 不会在主程序运行期对 PermGen space 进行清理,所以如果你的 APP 会 LOAD 很多 CLASS 的话 , 就很可能出现 PermGen space 错误。这种错误常见在 web 服务器对 JSP 进行 pre compile 的时候。
如果你的 WEB APP 下都用了大量的第三方 jar ,其大小超过了 jvm 默认的大小 (4M) 那么就会产生此错误信息了。
解决方法: 手动设置 MaxPermSize 大小
修改 TOMCAT_HOME/bin/catalina.sh , 在 echo "Using CATALINA_BASE: $CATALINA_BASE" 上面加入以下行: JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m 建议: 将相同的第三方 jar 文件移置到 tomcat/shared/lib 目录下,这样可以减少 jar 文档重复占用内存。
2 、转载:
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 (幼儿死亡率) ,这表示 越是新生成的变量或者对象,越容易被收集 。 下面一张图表示了对象的生命周期,横轴表示的是测试到对象的生命周期,纵轴表示在一个指定的生命周期上被回收的对象数量。
可以看到,在使用了分代收集法以后, 年轻一代的对象被收集的比例最高 。并且在内存中的对象会按照不同的 “ 年龄 ” 来划分,当一个年龄段的对象满了以后,在这个年龄段上就会发生垃圾收集,从最年轻的一×××始,一直到 “ 永生代 ” ,在内存中,所有的对象可以划分为很多代,最后的一代 “ 永生代 ” 就是 “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 启动的时候添加下面的参数来看 GC 的运行情况:
Java -verbosegc