因Java堆是Java对象在内存中使用的主要内存空间,当发生内存溢出或泄漏时,保存堆信息是问题产生原因的重要原料及问题分析的基础,而后才能分析追根溯源。
这里记录演示产生内存溢出生成堆转储文件,使用工具打开该文件进行初步分析的过程,作为备忘。
生成hprof文件
假设有以下程序
public class OOMHeapTest {
/**-XX:+HeapDumpOnOutOfMemoryError -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:SurvivorRatio=8*/
public static void main(String[] args){
oom();
}
private static void oom(){
Map<String, Pilot> map = new HashMap<String, Pilot>();
Object[] array = new Object[1000000];
for(int i=0; i<1000000; i++){
String d = new Date().toString();
Pilot p = new Pilot(d, i);
map.put(i+"dyh", p);
array[i]=p;
}
}
}
在运行vm参数中设置
-XX:+HeapDumpOnOutOfMemoryError -Xmx10m -Xms10m
设置堆大小为10MB,内存溢出时生成堆转储文件。堆转储文件如不设置存储目录,会保存于工程的根目录中 。文件后缀为hprof。
如上程序,跑完后在控制台有以下信息
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to java_pid15176.hprof ...
Heap dump file created [15615114 bytes in 0.059 secs]
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.dyh.jdk_jvm.heap.OOMHeapTest.oom(OOMHeapTest.java:24)
at com.dyh.jdk_jvm.heap.OOMHeapTest.main(OOMHeapTest.java:16)
到Java工程所在目录查看,有文件java_pid15176.hprof生成。
-XX:HeapDumpPath=F:/heapfile/heap_dump-%t.hprof,可指定文件路径
打开hprof文件进行工具分析的几种方式
打开hprof文件的工具有不少,jdk本身就有,另外还有不少厂商开发了专门的分析工具,这些工具有的可能比jdk的更好用。以下演示几种打开hprof文件的方法。
第一种,jdk/bin下的jhat
在jhat.exe的所在目录打开cmd(或者在其他目录打开cmd,然后引用该exe文件的路径亦可)
如jhat D:\yourpath\projectForTest\Eclipse_V4.6.1_projects\Eclipse_V4.6.1_projects_jdk_jvm\java_pid8128.hprof,这样就可为该堆转储文件生成报告,执行后的控制台信息
这说明堆转储文件的分析报告已经生成,可以在浏览器通过localhost:7000来访问,如
至于这个报告如何看,这里不再深入讨论。
第二种,IBM heapanalyzer
可通过IBM官网下载工具及阅读使用说明
https://www.ibm.com/support/pages/node/1109955?mhsrc=ibmsearch_a&mhq=heapanalyzer
如java -Xmx256m -jar ha456.jar可打开工具
加载完后视图
工具的分析报告不再深入讲解。
第三种,Eclipse Memory Analysis
eclipse也集成插件可以使用,可以集成到eclipse使用,也可以单独使用。可搜索“Eclipse Memory Analysis”获取。
单独运行MemoryAnalyzer.exe
分析报告页面