GC overhead limit exceeded – Java Heap analysis
by Pierre
Hugues Charbonneau on May 17th, 2012 | Filed in: Core Java
Tags: Garbage Collection, JVM
This post is the continuation of our
original GC overhead limit exceeded problem patterns post. Proper Java Heap
analysis is critical in order to eliminate your OutOfMemoryError: GC overhead
problem. If you are not familiar with this Java HotSpot 1.6 error, I recommend
that you first review my First Article on
this subject.
This article will provide you with a
sample program and a tutorial on how to analyze your Java HotSpot Heap
footprint using Memory Analyzer following an OutOfMemoryError. I highly
recommend that you execute and analyse the Heap Dump yourself using this
tutorial in order to better understand these principles.
Troubleshooting tools
** all these tools can be downloaded
for free **
- Eclipse Indigo Release
- Memory Analyzer via IBM Support Assistant 4.1 (HotSpot Heap Dump analysis)
- Java VM: Windows HotSpot JRE 1.6.0_24 64-bit
Sample Java program
The simple sample Java program below
will be used to triggered an OutOfMemoryError; allowing us to analyze the
generated HotSpot Heap Dump file. Simply create a new Java class :
JVMOutOfMemoryErrorSimulator.java to the Eclipse project of your choice and
either rename or keep the current package as is.
This program is basically creating
multiple String instances within a Map data structure until the Java Heap
depletion.
** please make sure your Eclipse
compiler and JRE is 1.6 **
01
|
package org.ph.javaee.javaheap;
|
|
02
|
|
03
|
import java.util.Map;
|
|
04
|
import java.util.HashMap;
|
05
|
|
|
06
|
/**
|
07
|
* JVMOutOfMemoryErrorSimulator
|
|
08
|
*
|
09
|
* @author PH
|
|
10
|
*
|
11
|
*/public class JVMOutOfMemoryErrorSimulator {
|
|
12
|
|
13
|
private final static int
NB_ITERATIONS = 500000;
|
|
14
|
|
15
|
// ~1 KB data
footprint
|
||
16
|
private final static String LEAKING_DATA_PREFIX =
"datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
|
||
17
|
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
|
18
|
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
|
19
|
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
|
20
|
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
|
21
|
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata";
|
||
22
|
|
||
23
|
// Map used to
stored our leaking String instances
|
|
24
|
private static Map<String, String>
leakingMap;
|
25
|
|
|
26
|
static {
|
27
|
leakingMap
= new HashMap<String,
String>();
|
|
28
|
}
|
29
|
|
|
30
|
/**
|
31
|
* @param
args
|
|
32
|
*/
|
33
|
public static void
main(String[] args) {
|
|
34
|
|
35
|
System.out.println("JVM
OutOfMemoryError Simulator
1.0");
|
36
|
System.out.println("Author:
Pierre-Hugues
Charbonneau");
|
37
|
System.out.println("
http ://javaeesupportpatterns.blogspot.com/");
|
|
38
|
|
39
|
try {
|
|
40
|
|
41
|
for (int
i = 0; i < NB_ITERATIONS; i++) {
|
|
42
|
|
43
|
String
data = LEAKING_DATA_PREFIX + i;
|
|
44
|
|
45
|
//
Add data to our leaking Map data structure...
|
|
46
|
leakingMap.put(data,
data);
|
47
|
|
|
48
|
}
|
49
|
|
|
50
|
}
catch (Throwable
any)
{
|
51
|
if (any instanceof java.lang.OutOfMemoryError){
|
|
52
|
System.out.println("OutOfMemoryError
triggered! "
|
53
|
+
any.getMessage() + " ["
+ any + "]");
|
|
54
|
|
55
|
}
else {
|
|
56
|
System.out.println("Unexpected
Exception! " +
|
57
|
any.getMessage()
+ " [" +
any + "]");
|
|
58
|
}
|
59
|
}
|
|
60
|
|
61
|
System.out.println("simulator
done!");
|
|
62
|
}
|
63
|
|
|
64
|
}
|
Step #1 – Setup your JVM start-up
arguments
First, setup your Eclipse Java
runtime arguments as per below. For our example, we used an external JRE 1.6
outside the Eclipse IDE with a Java Heap maximum capacity of 512 MB.
The key JVM argument allowing us to
generate a Heap Dump is -XX:+HeapDumpOnOutOfMemoryError which tells the JVM to
generate a Heap Dump following an OutOfMemoryError condition.
Step #2 – Run the sample Java
program
The next step is to run our Java
program. Depending on your computer specs, this program will run between 5-30
seconds before existing with an OutOfMemoryError.
As you can see, the JVM generated a
Heap Dump file java_pid3880.hprof . It is now time to fire the Memory Analyzer
tool and analyze the JVM Heap Dump.
Step #3 – Load the Heap Dump
Analyzing a Heap Dump is an analysis
activity that can be simple or very complex. The goal of this tutorial is to
give you the basics of Heap Dump analysis. For more Heap Dump analysis, please
refer to the other case studies of this Blog.
Step #4 – Analyze Heap Dump
Below are the snapshots and analysis
steps that you can follow to understand the memory leak that we simulated in
our sample Java program.
As you can see, the Heap Dump
analysis using the Memory Analyzer tool was able to easily identify our primary
leaking Java class and data structure.
Conclusion
I hope this simple Java program and
Heap Dump analysis tutorial has helped you understand the basic principles of
Java Heap analysis using the raw Heap Dump data. This analysis is critical when
dealing with OutOfMemoryError: GC overhead problems since those are symptoms of
either Java Heap leak of Java Heap footprint / tuning problem.
Reference:
GC overhead limit exceeded –
Java Heap analysis from our JCG
partner Pierre-Hugues Charbonneau at the Java EE Support Patterns & Java Tutorial
blog.
Comments
Post a Comment