Reading GC Logs in Java
GC logs are the most useful tool for understanding how a Java program uses memory. With one flag, the JVM writes a line for every garbage collection: what kind it was, why it ran, how much heap was used before and after, and how long the application was paused. Since Java 9, all JVM logging uses the unified logging option -Xlog. In this lesson, you will turn on GC logging, read real log lines, and learn what patterns to look for.
Turning on GC Logging
| Option | Logs |
|---|---|
-Xlog:gc | One line per collection |
-Xlog:gc* | Everything GC-related: setup, phases, heap regions, metaspace |
-Xlog:gc:file=gc.log | Writes the log to a file instead of the console |
-Xlog:gc*:file=gc.log:time,uptime,level,tags | Detailed log to a file with timestamps |
The old options -XX:+PrintGCDetails and -Xloggc no longer work.
Example: A Real GC Log
This program creates 2,000 arrays of 100 KB and keeps every tenth one. It was run with a 64 MB heap and GC logging:
import java.util.ArrayList;
import java.util.List;
public class Garbage {
public static void main(String[] args) {
List<byte[]> keep = new ArrayList<>();
for (int i = 0; i < 2_000; i++) {
byte[] chunk = new byte[100_000];
if (i % 10 == 0) {
keep.add(chunk);
}
}
System.out.println("Kept " + keep.size() + " chunks");
}
}java -Xlog:gc -Xmx64m Garbage.java[0.003s][info][gc] Using G1
[0.012s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 35M->4M(64M) 0.401ms
[0.013s][info][gc] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 30M->7M(64M) 0.327ms
[0.013s][info][gc] GC(2) Pause Young (Normal) (G1 Evacuation Pause) 37M->10M(64M) 0.227ms
[0.014s][info][gc] GC(3) Pause Young (Normal) (G1 Evacuation Pause) 43M->13M(64M) 0.481ms
[0.015s][info][gc] GC(4) Pause Young (Normal) (G1 Evacuation Pause) 46M->16M(64M) 0.355ms
[0.015s][info][gc] GC(5) Pause Young (Normal) (G1 Evacuation Pause) 50M->20M(64M) 0.301ms
Kept 200 chunksHow to Read a Line
| Part | Meaning |
|---|---|
[0.012s] | Time since the JVM started |
GC(0) | Collection number |
Pause Young (Normal) | A young-generation collection that paused the application |
(G1 Evacuation Pause) | The cause: eden filled up and live objects were evacuated |
35M->4M(64M) | Heap used before and after, and the total heap size |
0.401ms | Length of the pause |
Explanation: Each young collection reclaims most of the heap, but the "after" value climbs steadily (4M, 7M, 10M ... 20M) because every tenth array is kept. In a long-running program, an "after" value that keeps rising across many collections is a classic sign of a memory leak.
The Detailed Log
-Xlog:gc* adds much more detail. A real excerpt for the first collection above:
[0.016s][info][gc,start ] GC(0) Pause Young (Normal) (G1 Evacuation Pause)
[0.017s][info][gc,task ] GC(0) Using 2 workers of 9 for evacuation
[0.017s][info][gc,phases ] GC(0) Evacuate Collection Set: 0.35ms
[0.017s][info][gc,heap ] GC(0) Eden regions: 34->0(26)
[0.017s][info][gc,heap ] GC(0) Survivor regions: 0->4(5)
[0.017s][info][gc,heap ] GC(0) Old regions: 2->2
[0.017s][info][gc ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 35M->4M(64M) 0.521msIt shows that eden was emptied (34 regions to 0), live objects moved into 4 survivor regions, and the old generation didn't change.
Patterns to Look For
| Pattern | Likely meaning |
|---|---|
| "After" heap rising steadily over time | Memory leak or growing cache |
Frequent Pause Full collections | Heap too small, or a leak |
Pause Young very frequent | High allocation rate; consider reducing temporary objects |
| Long pauses only in full GCs | Old generation filling up |
To-space exhausted (G1) | Not enough free space to copy survivors; heap too small |
Common Mistakes
Using -XX:+PrintGCDetails. It was removed in Java 9; use -Xlog:gc*.
Judging from a single collection. Look at trends over many collections.
Ignoring the cause. "Allocation Failure", "Evacuation Pause" and "System.gc()" mean different things.
Practice
- Easy: Run
Garbagewith-Xlog:gc -Xmx32mand note how the number of collections changes. - Harder: Change
Garbageto keep every array, run it with-Xlog:gc -Xmx64m, and describe the log right before theOutOfMemoryError.
Key Takeaways
Was this tutorial helpful?