这篇文章是我们原来的GC超出限制的问题模式帖子的延续。
正确的Java堆分析对于消除OutOfMemoryError:GC开销问题至关重要。
如果您不熟悉此Java HotSpot 1.6错误,建议您首先阅读有关此主题的第一篇文章 。
本文将为您提供一个示例程序和一个教程,介绍如何在OutOfMemoryError之后使用Memory Analyzer分析Java HotSpot堆的占用空间。
我强烈建议您使用本教程自己执行和分析堆转储,以更好地理解这些原理。
故障排除工具
**所有这些工具都可以免费下载**
- Eclipse Indigo发布
- 通过IBM Support Assistant 4.1进行的内存分析器(热点堆转储分析)
- Java虚拟机:Windows HotSpot JRE 1.6.0_24 64位
示例Java程序
下面的简单Java示例程序将用于触发OutOfMemoryError;
使我们能够分析生成的HotSpot堆转储文件。
只需创建一个新的Java类:JVMOutOfMemoryErrorSimulator.java到您选择的Eclipse项目,然后重命名或保持当前包不变。
该程序基本上是在Map数据结构内创建多个String实例,直到Java Heap耗尽为止。
**请确保您的Eclipse编译器和JRE为1.6 **
package org.ph.javaee.javaheap;
import java.util.Map;
import java.util.HashMap;
/**
* JVMOutOfMemoryErrorSimulator
*
* @author PH
*
*/public class JVMOutOfMemoryErrorSimulator {
private final static int NB_ITERATIONS = 500000;
// ~1 KB data footprint
private final static String LEAKING_DATA_PREFIX = "datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata";
// Map used to stored our leaking String instances
private static Map<String, String> leakingMap;
static {
leakingMap = new HashMap<String, String>();
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("JVM OutOfMemoryError Simulator 1.0");
System.out.println("Author: Pierre-Hugues Charbonneau");
System.out.println(" http ://javaeesupportpatterns.blogspot.com/");
try {
for (int i = 0; i < NB_ITERATIONS; i++) {
String data = LEAKING_DATA_PREFIX + i;
// Add data to our leaking Map data structure...
leakingMap.put(data, data);
}
} catch (Throwable any) {
if (any instanceof java.lang.OutOfMemoryError){
System.out.println("OutOfMemoryError triggered! "
+ any.getMessage() + " [" + any + "]");
} else {
System.out.println("Unexpected Exception! " +
any.getMessage() + " [" + any + "]");
}
}
System.out.println("simulator done!");
}
}
步骤#1 –设置JVM启动参数
首先,按照以下步骤设置Eclipse Java运行时参数。
对于我们的示例,我们在Eclipse IDE外部使用了Java Jap最大容量为512 MB的外部JRE 1.6。
允许我们生成堆转储的主要JVM参数是-XX:+ HeapDumpOnOutOfMemoryError,它告诉JVM在OutOfMemoryError条件之后生成堆转储。
步骤#2 –运行示例Java程序
下一步是运行我们的Java程序。
根据您的计算机规格,此程序将在存在OutOfMemoryError之前运行5-30秒。
如您所见,JVM生成了一个堆转储文件java_pid3880.hprof。
现在是时候启动“内存分析器”工具并分析JVM堆转储了。
步骤#3 –加载堆转储
分析堆转储是一项简单或非常复杂的分析活动。
本教程的目的是为您提供堆转储分析的基础知识。
有关堆转储的更多分析,请参考此博客的其他案例研究。
步骤#4 –分析堆转储
下面是快照和分析步骤,可用来了解我们在示例Java程序中模拟的内存泄漏。
如您所见,使用Memory Analyzer工具进行的堆转储分析能够轻松识别我们主要的泄漏Java类和数据结构。
结论
我希望这个简单的Java程序和“堆转储”分析教程能够帮助您了解使用原始堆转储数据进行Java堆分析的基本原理。
处理OutOfMemoryError:GC开销问题时,此分析非常重要,因为这些是Java Heap占位面积/调整问题的Java Heap泄漏的症状。
翻译自: https://www.javacodegeeks.com/2012/05/gc-overhead-limit-exceeded-java-heap.html