第一种OutOfMemoryError: PermGen space (永久保存区域)

Permanent Generation space

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了

 

Generation space有关。解决这类问题有以下两种办法:

1. 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,XX:MaxPermSize是最大永久保存区域大小。如针对tomcat6.0,在catalina.sh 或catalina.bat文件中一系列环境变量名说明结束处(大约在70行左右) 增加一行:

JAVA_OPTS=" -XX:PermSize=64M -XX:MaxPermSize=128m"

如果是windows服务器还可以在系统环境变量中设置。感觉用tomcat发布sprint+struts+hibernate架构的程序时很容易发生这种内存溢出错误。使用上述方法,我成功解决了部署ssh项目的tomcat服务器经常宕机的问题。

2. 清理应用程序中web-inf/lib下的jar,如果tomcat部署了多个应用,很多应用都使用了相同的jar,可以将共同的jar移到tomcat共同的lib下,减少类的重复加载。这种方法是网上部分人推荐的,我没试过,但感觉减少不了太大的空间,最靠谱的还是第一种方法。

 

 

 

 

第二种OutOfMemoryError:  Java heap space (堆区域)

 

发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap space有关。

 

比如下面代码就会产生此种情况的内存溢出。

 

Set<Object> set = new HashSet<Object>();

 

for (int i = 0; i < 100000000; i++) {

 

set.add(new Object());

 

}

 

 

 

解决这类问题有两种思路:

 

1. 检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。

 

我以前写一个使用K-Means文本聚类算法对几万条文本记录(每条记录的特征向量大约10来个)进行文本聚类时,由于程序细节上有问题,就导致了Java heap space的内存溢出问题,后来通过修改程序得到了解决。

 

2. 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m

 

 

 

 

 

第三种OutOfMemoryError:unable to create new native thread

 

 

 

上面这种种溢出错误,已经说明了线程的内存空间,其实线程基本只占用heap以外的内存区域,也就是这个错误说明除了heap以外的区域,无法为线程分配一块内存区域了,这个要么是内存本身就不够,要么heap的空间设置得太大了,导致了剩余的内存已经不多了,而由于线程本身要占用内存,所以就不够用了。

 

 

 



 RUNTIME 类的使用:



 



Java 给我们提供了Runtime 类得到JVM 内存的信息



 方法名称

 参数

作用 

返回值 

 getRuntime 

 无

 获取Runtime 对象 

 Runtime 对象 

 totalMemory 

 无

 获取JVM 分配给程序的内存数量 

 long:内存数量 

 freeMemory

 无

 获取当前可用的内存数量 

 long:内存数量 

 maxMemory 

 无

 获取JVM 可以申请到的最大内存数量

 long:内存数量