今天给大家带来JVM体验之内存溢出问题的定位方法。
废话不多说直接开始:
一、Java堆溢出
测试代码如下:
package com.gosaint.ms;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class MemoryError {
static Vector<Emplyee> employeesList;
public static void main(String[] args) {
//雇员对象被保存在两个集合对象中,一个HashMap一个Vector,
//都分别持有Employee和Address的引用对象,这样这些对象就不会被GC当做垃圾回收
employeesList = new Vector<Emplyee>();
Map<Integer, Emplyee> employeesMap = new HashMap<Integer, Emplyee>();
int i = 0;
while (true) {
Emplyee emp1 = new Emplyee("Ram", new Address("MG Road", "Bangalore",
123, "India"));
Emplyee emp2 = new Emplyee("Bob", new Address("House No. 4",
"SCA", 234, "USA"));
Emplyee emp3 = new Emplyee("John", new Address("Church Street",
"Bangalore", 569, "India"));
employeesMap.put(new Integer(i++), emp1);
employeesList.add(emp1);
employeesMap.put(new Integer(i++), emp2);
employeesList.add(emp2);
employeesMap.put(new Integer(i++), emp3);
employeesList.add(emp3);
emp2.addReports(emp1);
emp3.addReports(emp1);
emp3.addReports(emp2);
}
}
}
class Emplyee {
public String name;
public Address address;
public Vector<Emplyee> directReports;
public Emplyee(String name, Address address) {
this.name = name;
this.address = address;
directReports = new Vector<Emplyee>();
}
public void addReports(Emplyee emplyee) {
directReports.add(emplyee);
}
}
class Address {
public String addr;
public String city;
public int zip;
public String country;
public Address(String addr, String city, int zip, String country) {
this.addr = addr;
this.city = city;
this.zip = zip;
this.country = country;
}
}
我们在这里可以看到内存在不断的上涨,而Java在到一定时候会爆出OOM异常。
如下:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.Vector.<init>(Unknown Source)
at java.util.Vector.<init>(Unknown Source)
at java.util.Vector.<init>(Unknown Source)
at com.gosaint.ms.Emplyee.<init>(MemoryError.java:49)
at com.gosaint.ms.MemoryError.main(MemoryError.java:23)
现在程序是很简单,不过如果在大型项目里爆了堆溢出可就麻烦了。
我们很难通过代码定位。
所以我们需要用工具对其分析。
二、堆内存快照
我们先对Eclipse进行运行配置。
参数如下所示-XX:+HeapDumpOnOutOfMemoryError -Xms20m -Xmx20m
运行结果如下:
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to java_pid15464.hprof ...
Heap dump file created [34821332 bytes in 0.222 secs]
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
随后我们找到项目地址,我们会发现在Project本目录中出现了个hprof文件
三、分析
我们发现对象主要最大的是13.2M,然后是4.3M,打开Domainator Tree
分别在主线程和com.gosaint.ms.MemoryError这个类里面的Vector容器里面,这样我们就可以去定位到具体的代码了。