Java应用程序占用的内存在不断的、有规律的上涨,最终超过了监控阈值。 就是内存泄漏
分析内存泄露的一般步骤
如果发现Java应用程序占用的内存出现了泄露的迹象,那么我们一般采用下面的步骤分析
- 把Java应用程序使用的heap dump下来
- 使用Java heap分析工具,找出内存占用超出预期(一般是因为数量太多)的嫌疑对象
- 必要时,需要分析嫌疑对象和其他对象的引用关系。
- 查看程序的源代码,找出嫌疑对象数量过多的原因。
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TestMemoryLeak {
@Test
public void test01() {
List<MyObject> myObjects = new ArrayList<MyObject>();
while(true){
myObjects.add(new MyObject());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyObject{
private String sss;
private int ss;
private List<String> list = new ArrayList<String>(10000);
}
}
如上图给虚拟机加参数:-verbose:gc -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError ,那么每次gc的时候就会在控制台打印日志,如下图
jconsole工具是jdk自带的jvm分析工具,可以分析线程、内存、加载的类等。 每次gc的时候内存都会有明显的回收。
如上图就是每次jc内存都没有明显的回收,内存使用量持续上升,一直到JVM报错java.lang.OutOfMemoryError: Java heap space,程序停止。这就是明显的内存泄漏。
如果Java应用程序出现了内存泄露,千万别着急着把应用杀掉,而是要保存现场。保存现场的目的就是为了把 运行中JVM的heap dump下来。
jmap -dump:format=b,file=heap.bin <pid>
format=b的含义是,dump出来的文件时二进制格式。
file-heap.bin的含义是,dump出来的文件名是heap.bin。
<pid>就是JVM的进程号。
将二进制的heap dump文件解析成human-readable的信息,自然是需要专业工具的帮助,这里推荐Memory Analyzer 。
Memory Analyzer,简称MAT,是Eclipse基金会的开源项目,由SAP和IBM捐助。巨头公司出品的软件还是很中用的,MAT可以分析包含数亿级对 象的heap、快速计算每个对象占用的内存大小、对象之间的引用关系、自动检测内存泄露的嫌疑对象,功能强大,而且界面友好易用。
如下图就是MAT分析的结果:
明显的ArrayList中MayObject对对象占用了大量的内存,利用Path To GC Roots功能可以对应的引用路径,然后分析代码找到内存泄漏的原因.
如