在前期博文中,堆已经讲得差不多啦,这章我们以一个例子来说说如何设置以及当发生堆溢出的时候怎么排查问题。先看一小段代码:
public class Test {
private static List<Test> list = new ArrayList<Test>();
private static void main(String[] args) {
while(true){
Test test = new Test();
list.add(test);
}
}
}
二、参数设置
上面的代码中使用了一个无限循环来为list添加对象,如果采用默认的堆大小的话可能要等待好久才能出现堆溢出的错误,因此我们要将其设置小一点:
-Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
,elipse
中的设置方法我们在前期博文《JVM进阶(一):初识 JAVA 栈》讲过了,这里不多说啦。-Xms10m
,意思就是堆的最小内存为10m。同理-Xmx10m
的意思就是最大内存也为10m。这两个都是设置为10m,那么堆的大小就是10m。而-XX:+HeapDumpOnOutOfMemoryError
指的是当发生内存溢出的时候会将当前的内存使用情况生成一个快照保存起来,但需要eclipse
下载一个MAT
插件,下载方式自行百度。
三、问题排查
使用刚刚设置的参数启动程序,稍等一小会就会出现以下错误:
显示出堆溢出错误,并且生成了一个叫做java_pid4792.hprof
的文件,我们刷新项目便可以看到该文件,双击打开,需要一段的加载时间。
首先可以看到的是一个饼状图,占用部分最大的便是发生溢出错误的部分,我们接着往下看 :
我们这里看看画红线的部分,这里列出一些存活的大对象,在溢出的时候一般先怀疑大对象,我们点进去:
这里列出占用内存最大的几个对象,很显然,第一个很可疑,占用率达到了94.64%!继续跟进:
发现都是test对象,因此排查的时候可以从这个方面下手。接着我们右键该对象选择Path To GC Root
(在引用链上的路径),再选择exclue all phantom/weak/soft etc. reference
,结果如图:
可以看到是被List引用了,因此一直在引用链上,导致无法被回收掉,也就出现了内存溢出。
本文只讲了MAT
的一个最基本的用途,指出排查思路,感兴趣的小伙伴可以结合工作上的案例自己深入的去了解其更多的用途。
四、拓展阅读
- 《JVM虚拟机专栏》
JavaScript
-
js的基本类型有哪些?引用类型有哪些?null和undefined的区别。
-
如何判断一个变量是Array类型?如何判断一个变量是Number类型?(都不止一种)
-
Object是引用类型嘛?引用类型和基本类型有什么区别?哪个是存在堆哪一个是存在栈上面的?
-
JS常见的dom操作api
-
解释一下事件冒泡和事件捕获
-
事件委托(手写例子),事件冒泡和捕获,如何阻止冒泡?如何组织默认事件?
-
对闭包的理解?什么时候构成闭包?闭包的实现方法?闭包的优缺点?
-
this有哪些使用场景?跟C,Java中的this有什么区别?如何改变this的值?
-
call,apply,bind
-
显示原型和隐式原型,手绘原型链,原型链是什么?为什么要有原型链
-
创建对象的多种方式
-
实现继承的多种方式和优缺点
-
new 一个对象具体做了什么
-
手写Ajax,XMLHttpRequest
-
变量提升
-
举例说明一个匿名函数的典型用例
-
指出JS的宿主对象和原生对象的区别,为什么扩展JS内置对象不是好的做法?有哪些内置对象和内置函数?
-
attribute和property的区别
-
document load和document DOMContentLoaded两个事件的区别
-
JS代码调试