起笔:
文章的源起在于本人想向道哥(导演)拿一份公司Dump文件。
问题描述
本地模拟可能产生OOM的几十种不同的方法(自由发挥),然后通过类随机去调用方法,通过Dump文件分析是哪个方法导致程序的OOM
代码实现:
分析工具:
过程:
- 第一步 :设置jvm参数
-Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError
- 第二步:启动程序,生成Dump文件
public static void main( String[] args ) throws Exception {
Random random = new Random();
RandomOOM randomOOM = new RandomOOM();
int i1 = random.nextInt(4);
randomOOM.Entrance(i1);
}
- 第三步:分析Dump文件
-
打开dump文件
可以思考一下为什么这里只有堆遍历器是亮的
-
分析内存
-
将对象按大小排序
这里排序完毕可以看到Character数组占了非常的多的内存,其他Object等类占的内存相对较小,其实在这里我们就可以知道,程序产生OOM的原因是因为Character数组对象创建过多,而且Character数组对象又无法被jvm进行回收(当然现实生产中OOM产生的原因不能这么简单地去概括,还需要结合实际情况去分析,具体情况具体分析)
-
排序后的结果:
-
对象的引用分析:
选择传入引用
这里可以看到这些Character数组都大小一致,也大概可以知道应该是一个对象引用了他们,然后我们需要去分析Character数组的引用对象有哪些,最后定位问题代码所在(当然现实场景中,这里也可能更复杂,可能这里的Character数组对象大小不同,那么是怎么造成的内存泄漏又需要我们灵活地去分析!!)
选中在图表中显示,这里也可以选择显示道GC根的路径,但是为了方便观看,通过图表无疑是最佳的
图表的初始面貌
这里我们可以知道是一个Object对象引用了Character[]对象导致Character[]对象无法被jvm回收,那么这个Object是被什么类引用导致无法被回收了?依次分析下去
分析到这一步的时候,大家可能会有疑惑,Object类有两个类去引用了它,那么该分析那个类的引用关系才能将问题定位到出现问题的方法中呢?这里因为这个代码是我本人写的,所以我知道那个类能最快定位问题出现的方法中,因此直接选的OOMObject(真实场景中,会比这个更加复杂,可能会有几十到几百个类,这就需要我们去根据代码仔细考量一番!)
最后到了这一步,其实就已经知道了造成OOM问题的罪魁祸首在于OOMObject#_16方法中,因此我们直接去这个类中找方法分析代码就行了!!
-
-