这篇文章是我们原来的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泄漏的症状。
参考: 超出了GC开销限制– Java EE支持模式和Java教程博客中的JCG合作伙伴 Pierre-Hugues Charbonneau进行了Java 堆分析 。
翻译自: https://www.javacodegeeks.com/2012/05/gc-overhead-limit-exceeded-java-heap.html