Java内存溢出分析及总结

1 篇文章 0 订阅

背景

在解决某次现场问题时遇到了内存泄漏,通过对平台进行定位分析,并结合之前的经验整理了此文档。

问题分析

java.lang.OutOfMemoryError这个报错相信是很多做java开发人员的噩梦,特别对于一些新人程序员来说,第一次遇到往往思路全无,其实产生该错误的原因大多出于以下原因:JVM内存过小、程序逻辑不严密、产生过多垃圾。

一、常见的错误提示

  • tomcat:java.lang.OutOfMemorryError: PermGen space

这一部分用于存放Class和Meta的信息,Class在被Load的时候被放入PermGen space区域(包括常量池:静态变量),它和存放Instance的Heap区域不同,GC不会在主程序运行期间对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
这种错误常见在web服务器,可以通过设置jvm启动参数来解决: -XX:MaxPermSize=256m

  • tomcat:java.lang.OutOfMemoryError:java heap space

这部分用于存放类的实例。被缓存的实力(Cache)对象,大的map,list引用大的对象等等,都会保存在这里。
堆内存会在jvm启动时自动设置,初始值为 -Xms为物理内存的1/64,最大值 -Xmx为1/4; 可以通过参数 -Xmn 、-Xms、
-Xmx设置,一般-Xms、 -Xmx不超过80%,-Xmn为-Xmx的1/4

  • java:java.lang.OutOfMemoryError

这部分用于存放局部变量、方法栈帧信息。栈帧太多,也就是函数调用层级过多时就会出现此异常,需要检查是否有死递归的情况。
对应的启动参数为: -Xss(JDK1.5之后默认是1M,之前是256K)
实例,以下是1G内存环境下java jvm的参数设置参考:
JAVA_OPTS="-server -Xms800m -Xmx800m
-XX:PermSize=64M -XX:MaxNewSize=256m
-XX:MaxPermSize=128m -Djava.awt.headless=true

导致内存溢出的常见原因

  • 内存中加载的数据量过于庞大,如一次从数据库取出过多数据
  • 集合类中有对对象的引用,使用完未清空,使得JVM不能回收
  • 代码中存在死循环或循环产生过多重复的对象实体
  • 使用的第三方软件中的BUG
  • 启动参数内存设定的过小

解决内存溢出的方法

1) 增加jvm的内存大小

  • 在执行某个class文件的时候,可以使用java -Xmx256 aa.class来设置运行aa.class时jvm所允许占用的最大内存为256M
  • 对tomcat容器,可以在启动时对jvm设置内存限度。对tomcat可以在catalina.bat中添加:
    set CATALINA_OPTS=-Xms128M -Xmx256M
    set JAVA_OPTS=-Xms128M  - Xmx256M

或者把%CATALINA_OPTS%和%JAVA_OPTS%代替为Xms128M -Xmx256M

2)优化程序,释放垃圾构造方法等
主要包括避免死循环,应该及时释放各种资源:内存、数据库连接、防止一次性载入太多数据。导致java.lang.OutOfMemoryError的根本原因是程序不健壮。因此,从根本上解决java内存溢出的唯一方法就是修改程序,及时释放没有用的对象,释放内存空间。遇到该错误的时候要仔细检查程序,需要重点排查以下几点:

  • 检查代码中是否有死循环或者递归调用。
  • 检查是否有大循环重复产生新对象实体。
  • 检查对数据库查询中,是否一次性获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就可能引起内存溢出。因此对于数据库查询尽量采用分页的查询方式。
  • 检查List、Map等集合对象是否使用完之后,未清除。List、Map等集合对象会始终存有对对象的引用,是的这些对象不能被GC回收。

dump排查方案

以上方法都无法快速定位问题或者解决时,可以尝试使用dump文件进行问题的深度定位。jvm启动时添加参数
-XX:+HeapDumpOnOutOfMemoryError,这样当内存溢出时,会生成dump文件。通过dump文件使用专门的分析工具可以查看类的使用情况。推荐使用工具Eclipse Memory Analyzer。当然也可以使用Jprofile进行动态实时分析。两个工具网上都有详细教程:
http://blog.csdn.net/chendc201/article/details/22897999
http://essen.iteye.com/blog/1825314

经验总结

内存溢出不像普通的缺陷,可以通过简单的功能测试被发现,大多数的内存问题都是在系统运行相当一段时间后才显露出来,因此我们需要在平时去重视,建议将部分的要求纳入代码审核工作的检查项中,有目的有方向的检查执行,就可以大大降低内存溢出的风险。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值