诊断Java.lang.OutOfMemoryError(OOM)

在跟踪性能问题时,堆内存是首先应该被监控的最重要的组件之一。一旦堆内存的实际使用量超过其所允许的堆空间,就会产生堆内存压力。而这将导致频繁的全面垃圾回收事件,垃圾回收将窃取CPU周期,轻则导致响应时间延迟,重则导致必须重新启动Java虚拟机才能解决的内存溢出错误。

内存溢出错误(OOM)
当我运行应用时,出现了如下异常:

  • java.lang.OutOfMemoryError: GC overhead limit exceeded[7,9]
  • java.lang.OutOfMemoryError: Java heap space

第一条信息意味着,出于某种原因,垃圾收集器每次执行都花费了大量时间但只回收了很少量的内存,当我删除了如下代码后:

System.gc();

第一条信息消失了,取而代之的,系统出现了第二条信息。很明显堆内存空间依然存在问题。下面是我调查问题的步骤:

  1. 添加下面的Java启动参数
    • -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
      • 系统会生成gc.log文件
    • -XX:+HeapDumpOnOutOfMemoryError
      • 系统会生成堆内存转储文件
  2. 分析日志文件:
    • 使用常规的文本编辑器查看gc.log 文件。
    • 使用 Eclipse Memory Analyzer 查看 堆内存转储文件 (例如, java_xxx.hprof)

请注意,本文所讨论的所有虚拟机参数都是基于Hotspot虚拟机的。

Java命令行参数说明:

  • -XX:+PrintGCDetails
    • 打印更多的关于垃圾收集的信息。
  • -XX:+PrintGCTimeStamps
    • 打印从HotSpot 虚拟机开始执行直至垃圾收集事件发生所花费的时间(以秒为单位)。
  • -Xloggc:gc.log
    • 在每次垃圾收集时打印堆内存以及垃圾收集的信息。

在JDeveloper中可以按照如下方式设定:

  1. 右键选择你的项目(例如ViewController),显示出菜单
  2. 选择Project Properties…
  3. 选择Run/Debug/Profile
  4. 选择你Run Configuration(例如, Default)
  5. 点击Edit按钮
  6. 在Java虚拟机参数栏位设定 -Xloggc:gc.log -XX:-PrintGCDetails

运行你的应用并重现内存溢出异常,系统将会生成日志文件gc.log,
我的是在如下目录:

  • …/system11.1.1.5.37.60.13/DefaultDomain

因为我的Web应用是部署在集成的WLS中,并且通过DefaultDomain来执行。
所以,想要理解gc.log文件的格式,请参考关联阅读[5,15]。

不过,gc.log文件并不能真正的帮到我们,因为他只是简要的打印了堆内存问题,

但并没有指出问题出在哪。
接下来我要做的是添加如下参数,并重新执行服务。
-XX:+HeapDumpOnOutOfMemoryError
当服务发生堆内存错误时,会生成java_pid30835.hprof文件。

 Eclise内存分析器(Eclipse Memory Analyzer

堆内存转储文件由HPROF(堆内存和CPU分析工具)生成,堆内存转储文件是2进制格式的,因此必须使用Eclpse Memory Analyzer 来查看。

你可以通过Eclipse Update manager 来安装Eclipse MAT,选择”General Purpose Tools “并安装”Memory Analyser (Incubation)”以及”Memory Analyser (Charts)”。

安装之后,双击堆内存转储文件并且选择”Leak Suspects Report”

Eclipse MAT会显示如下图表:

以及问题的嫌疑人:

 

调整堆内存空间

如果你观察到垃圾收集日志文件中有内存溢出错误,那么可以尝试将Java堆内存空间调整为你能够分配给Java虚拟机的物理内存空间的80%,基于具体是老年代空间还是永久代空间发生内存溢出,你可以像这样调整内存空间。

  • 针对老年代发生内存溢出
    • increase -Xms and -Xmx
  • 针对永久代发生内存溢出
    • increase -XX:PermSize and -XX:MaxPermSize

参考文献:

  1. Eclipse Update Manager
  2. Eclipse Memory Analyzer
  3. Java Hotspot VM Options
  4. Integrated WebLogic Server (WLS)
  5. Diagnosing a Garbage Collection problem
  6. Frequently Asked Questions about Garbage Collection
  7. GC Overhead Limit Exceeded
  8. HPROF: A Heap/CPU Profiling Tool in J2SE 5.0
  9. Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
  10. Java Performance by Charlie Hunt and Binu John
  11. Understanding Garbage Collection
  12. Java HotSpot VM Options
  13. GCViewer (a free open source tool)
  14. Understanding Garbage Collector Output of Hotspot VM

 

英文原文:xmlandmore,编译:ImportNew-王晓杰

译文地址: http://www.importnew.com/1586.html

【如需转载,请在正文中标注并保留原文链接、译文链接和译者等信息,谢谢合作!】

关于作者: 王晓杰

王晓杰。已过而立之年,毕业于北京工业大学,计算机科学与技术学士学位。 PMP,SCJP,SCWCD。 目前就职于高森明晨信息科技有限公司,任助理产品总监。 潜心学习中,目前主要方向为Java分布式系统架构,Java虚拟机,Android应用。 平时喜爱打篮球和厨艺。

查看王晓杰的更多文章 >>



相关文章

发表评论

Comment form

(*) 表示必填项

还没有评论。

跳到底部
返回顶部