OOM浅析

相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深入的认识。参照网上的一些解决方案,在这里加以整理。

在解决java内存溢出问题之前,需要对jvm(java虚拟机)的内存管理有一定的认识。jvm管理的内存大致包括三种不同类型的内存区域:
Permanent Generation space(永久            保存区域)、Heap space(堆区域)、Java Stacks(Java栈)。


         永久保存区域主要存放Class(类)和Meta的信息,Class第一次被Load的时候被放入PermGen space区域,Class需要存储的内容主要包括方法和静态属性。


         堆区域用来存放Class的实例(即对象),对象需要存储的内容主要是非静态属性。每次用new创建一个对象实例后,对象实例存储在堆区域中,这部分空间也被jvm的垃圾回收机制管理。


         Java栈跟大多数编程语言包括汇编语言的栈功能相似,主要基本类型变量以及方法的输入输出参数。Java程序的每个线程中都有一个独立的堆栈。

容易发生内存溢出问题的内存空间包括:Permanent Generation space和Heap space。

第一种OutOfMemoryError: PermGen space


发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够,与Permanent 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有关。解决这类问题有两种思路:

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

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

第三种OutOfMemoryError:unable to create new native thread


这种错误在Java线程个数很多的情况下容易发生,我暂时还没遇到过,发生原意和解决办法可以参考:


http://hi.baidu.com/hexiong/blog/item/16dc9e518fb10c2542a75b3c.html

参考自:http://blog.sina.com.cn/s/blog_701c951f0100n1sp.html

代码中如何查看JVM内存设置信息


1、Runtime.getRuntime().maxMemory(); 

        最大可用内存,对应-Xmx;为JVM的最大可用内存,可通过-Xmx设置,默认值为物理内存的1/4,设值不能高于计算机物理内存;


2、Runtime.getRuntime().freeMemory(); 

         当前JVM空闲内存;其为当前JVM空闲内存,因为JVM只有在需要内存时才占用物理内存使用,所以freeMemory()的值一般情况下都很小,而JVM实际可用内存并不等于freeMemory(),而应该等maxMemory()-totalMemory()+freeMemory().及其设置JVM内存分配。


3、Runtime.getRuntime().totalMemory();

当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和。为当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和,会随着JVM使用内存的增加而增加;

修改了这些配置没有用,怎么办?


1、修改ini文件

         在eclipse.ini文件中将默认设置改为-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M或者更大,这要看你自己机器的内存配置而定;


2、在IDE中修改配置

        打开eclipse,选择Window--Preferences...在对话框左边的树上双击Java,再双击Installed JREs,在右边选择前面有对勾的JRE,再单击右边的“Edit”按钮,出现一个 Edit JRE 的对话框,在其中的Default VM Arguments: 框中输入 -Xms128m -Xmx512m ,这样设置Java拟虚机内存使用最小是128M,最大是512M,再单击“OK”关闭 Edit JRE 对话框,再单击“OK”关闭 Preferences对话框;


3、在快捷方式标签下修改

        如果这样还解决不了,就右击eclipse快捷方式,在属性---快捷方式标签下---目标中输入D:\eclipse\eclipse.exe -clean -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M,其中D:\eclipse\eclipse.exe是eclipse的位置,就可以了。

参考自:http://www.360doc.com/content/12/0504/18/1527319_208660024.shtml

补充各参数含义


-vmargs:说明后面是VM(即Myeclipse虚拟机)的参数

 -Xms128m:虚拟机占用系统的最小堆内存为128M

 -Xmx512m:虚拟机占用系统的最大堆内存为512M

 -XX:PermSize=128m:最小堆大小(最小永久保存区域)。一般报内存不足时,都是说这个太小,堆空间剩余小于5%就会警告,建议把这个稍微设大一点,不过要视自己机器内存大小来设置。

 -XX:MaxPermSize=256m:最大堆大小(最大永久保存区域)。这个也适当大些。

 注意: -Xmx512M的5%为25.6M,理论上要求-Xmx的数值与-XX:MaxPermSize必须大于25.6M.

 所以,按照上面的方法适当进行修改,下面是我电脑上配置的:

 -vmargs

 -Xms128m

 -Xmx512m

 -XX:PermSize=64m

 -XX:MaxPermSize=128m

 -XX:ReservedCodeCacheSize=64m

如何监视jvm内存?使用jvisualvm

不能一味加内存解决问题,最好定期检查一下程序对内存的消耗,以避免潜 在的内存溢出。建议大家使用jvisualvm来监控JVM。(JDK自带,命令行直接打jvisualvm即可),下面是工具截图,参考自:

http://my.oschina.net/zmen/blog/108989

java.lang.OutOfMemory总结分析的更多相关文章

  1. java.lang.ArrayIndexOutOfBoundsException异常分析及解决

    这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么下标越界. 下面是一个错误示例: Exception in thread "main" java.lan ...

  2. java.lang.ArrayIndexOutOfBoundsException 异常分析及解决

    参考:http://blog.csdn.net/javaeeteacher/article/details/4485834 这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么 ...

  3. Java.lang的研究(分析包含的重要类和接口)

    Java.lang包是Java中使用最广泛的一个包,它包含很多定义的类和接口. java.lang包包括以下这些类: Boolean Byte Character Class ClassLoader ...

  4. “java.lang.NullPointerException”异常分析

    1.父类定义的某个属性,没有被子类使用,或者在子类中,又重新定义一次. 2.因为调用了一个object的方法,且此object的reference为null:比如说:String a=null; // ...

  5. java.lang.ExceptionInInitializerError异常分析

    今天在项目开发时遇到一个问题,整个项目是使用Spring等框架搭建起来的在运行项目时不报任何的异常信息,就是找不到某个类信息,各方查找该类确实是存在的,最后通过断点跟踪时在异常栈内发现java.lan ...

  6. java.lang.UnsupportedOperationException 异常分析

    今天将一个数组转换成 List 然后进行 remove 操作时却抛出 java.lang.UnsupportedOperationException 异常. String pattern = &quo ...

  7. 【Java中的线程】java.lang.Thread 类分析

    进程和线程 联想一下现实生活中的例子--烧开水,烧开水时是不是不需要在旁边守着,交给热水机完成,烧开水这段时间可以去干一点其他的事情,例如将衣服丢到洗衣机中洗衣服.这样开水烧完,衣服洗的也差不多了.这 ...

  8. Linux下jetty报java.lang.OutOfMemoryError: PermGen space及Jetty内存配置调优解决方案

    Linux下的jetty报java.lang.OutOfMemoryError: PermGen space及Jetty内存配置调优解决方案问题linux的jetty下发布程序后再启动jetty服务时 ...

  9. 【转载】java项目中经常碰到的内存溢出问题: java.lang.OutOfMemoryError: PermGen space, 堆内存和非堆内存,写的很好,理解很方便

    Tomcat Xms Xmx PermSize MaxPermSize 区别 及 java.lang.OutOfMemoryError: PermGen space 解决 解决方案 在 catalin ...

随机推荐

  1. bzoj1564

    嗯,这是一道简单题 注意二叉搜索树的子树中序一定是连续的 又因为取值修改是任意的并且修改代价与权值无关 不难想到把权值离散化,然后按找数据值排序,然后dp f[i][j][w]表示从i~j的节点构成一 ...

  2. TYVJ 1066 合并果子【优先队列】

    题意:给出n堆果子,需要将n堆果子合并成一堆,问将所有堆的果子合成一堆所需要花费的最少的力气 因为要使耗费力气最小,即需要每次搬动的那堆重量小,所以可以选取两堆最轻的合并,合并之后再插入还没有合并的堆 ...

  3. HTTP请求头host解析

    Host: 域名 Host表示请求的服务器网址:   request headers中的host字段 例如有user.xiaoqiang.com,hotel.xiaoqiang.com 现在需要登录后 ...

  4. tomcat 默认项目设置

    正常情况下,我们启动tomcat后,直接输入“http://localhost:端口/“ 后,默认访问道是webapp目录下的ROOT应用. 我们要通过上述方式访问自己的应用,有俩种方式. 第一:把自 ...

  5. Windows Azure® 由世纪互联运营发布MySQL Database on Azure正式商用版

    我们很高兴宣布MySQL Database on Azure于2015年9月1日在中国地区正式商用.回望过去,从2014年12月对少量用户开放的预览试用,到2015年4月30日对中国用户全面开放的公共 ...

  6. 图文详解YUV420数据格式

    YUV格式有两大类:planar和packed.对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V.对于packed的YUV格式,每个像素点的Y,U ...

  7. zoj 1842 Prime Distance

    // 数论题,增强的筛法,回想素数筛法 // 只要筛到最大数的开方,剩下的就是素数 // 于是这里,开一个 sqrt(2^31) 大约 65536 的素数表,然后 // 对于每个 L~U 的区间,筛掉 ...

  8. Winform使用DevExpress的WaitDialogForm画面 z

    使用了DevExpress的WaitDialogForm 在应用程序加载开始时新建一个线程,并将loading画面show起来,在应用程序画面弹出前将该线程终止. 代码: private DevExp ...

  9. CCCallFuncN误用导致引用计数循环引用

    昨天测试“角色被遮挡部分透明显示”功能时,发现角色死亡后,其轮廓精灵不会消失.调试发现,角色在死亡时,其引用计数retain_count居然是9.这是由引用计数混乱引起的内存泄露. 加了很多日志跟踪r ...

  10. Core Java 学习笔记——2.基本数据类型&类型转换

    数据类型(8种基本类型:int/short/long/byte/float/double/char/boolean) 整型 int 4字节 -2 147 483 648~2 147 483 647 s ...