当前位置: 首页 > Java > 正文

Java OOM示例、原因查找和解决(二)

1 星2 星3 星4 星5 星 (2 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share

以-Xms20m -Xmx20m -Xmn10m -XX:+HeapDumpOnOutOfMemoryError执行com.bluedavy.oom.JavaHeapSpaceCase2

运行后在输出的日志中可看到大量的Full GC和java.lang.OutOfMemoryError: Java heap space。

同样,首先用mat打开需要分析的hprof文件,很惊讶的发现什么都看不出来,Java Heap Space还很充足,这就奇怪了,还好除了能在OOM时自动dump出Heap的信息外,还可通过jmap命令手工dump,于是,在运行期出现频繁Full GC、OOM的时候,手工通过
jmap –dump:file=heap.bin,format=b [pid]生成一个heap.bin文件,把这个heap.bin文件也拿到mat中分析,杯具,还是什么都看不出来,还好,还有一招,就是直接用jmap –histo看看到底什么对象占用了大多数的内存,执行一次,看到[I占用了最多的内存,没用,因为没法知道这个[I到底是代码中哪个部分创建的,不甘心,多执行几次,很幸运,突然看到com.bluedavy.oom.Case2Object占据了最大的内存,于是查找代码中哪些地方创建了这个对象,发现了代码中有一个线程创建了大量的Case2Object,修改即可。

从这个例子中,可以看到,在分析OOM问题时,一方面是依赖OOM时dump出来的文件,但这个文件其实只会在Java进程中第一次出现OOM时生成,之后再OOM就不会生成了,这有可能出现真实的OOM的原因被假的OOM原因给掩盖掉;另一方面是依赖在出现OOM时的人工操作,这种人肉方式其实比较杯具。
 
因为只能先等到频繁Full GC、OOM,首先通过jmap –histo来看看到底什么对象占用了大部分的内存(需要多执行几次,以确保正确性),上面的例子比较幸运,因为刚好是自定义的对象,如果是原生的类型,那就只能借助dump文件来分析了,通过jmap –dump手工dump出Heap文件。

然后用MAT分析,但有可能会出现上面例子中的状况,就是mat分析上也看不出什么,顶多只能看到unreachable objects里某些对象占用了大部分的内存,而通常情况看到的可能都是原生类型,一旦真的碰到jmap –histo看到的是原生类型占用较多,jmap dump看到的是Java Heap Space也不满的话,那只能说杯具了,在这种情况下,唯一能做的是捕捉所有的异常,然后打印,从而判断OOM是在哪行代码抛出的。

本文固定链接: http://www.chepoo.com/java-oom-demo-error-solution-2.html | IT技术精华网

Java OOM示例、原因查找和解决(二):等您坐沙发呢!

发表评论