Java Performance Tuning Part 1: Understanding the JVM Memory Model from a GC Log
This article launches a Java performance tuning series, explaining why GC logs are the starting point, reviewing the JVM memory model, showing how to enable and read GC logs, dissecting minor and full GC entries, comparing common GC algorithms, and introducing visualization tools to help pinpoint memory issues.
Why start with a GC log
Garbage Collection (GC) is central to Java performance tuning; about 80% of performance problems are related to memory management. A GC log shows heap usage, GC frequency, memory‑leak risk and provides data for further optimization.
JVM memory model (Java 8 baseline)
┌─────────────────────────────────────────────────────────────────┐
│ JVM Memory Model │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Heap Memory │ │
│ │ ┌───────────────┐ ┌───────────────────────────────┐ │ │
│ │ │ Young Gen │ │ Old Gen │ │ │
│ │ │ (Eden, S0, S1)│ │ │ │ │
│ │ └───────────────┘ └───────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Non‑Heap Memory │ │
│ │ ┌───────────────┐ ┌───────────────────────────────┐ │ │
│ │ │ Metaspace │ │ Thread Stack / PC │ │ │
│ │ └───────────────┘ └───────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘Object allocation and promotion flow:
New Object → Eden → Survivor 0 → Survivor 1 → Old Generation
│ │ │ │
│ Minor GC survivors │ Major GC │
▼ ▼ ▼ ▼
Allocation fail Age+1 Age+1 Final reclamationCore concepts quick reference
Eden : allocation site for new objects; most objects have short lifetimes. Triggered by Minor GC.
Survivor 0/1 : objects that survive a Minor GC; their age increments.
Old Generation : objects promoted after reaching the default age threshold (15) or large objects allocated directly. Triggered by Major/Full GC.
Metaspace : stores class metadata in native memory (Java 8+). Triggered by Full GC.
Enabling GC logging
For JDK 8/11/17 the following options write detailed GC information to gc.log:
java -Xloggc:gc.log \
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-XX:+PrintGCTimeStamps \
-XX:+PrintHeapAtGC \
-XX:+PrintGCApplicationConcurrentTime \
-XX:+PrintGCApplicationStoppedTime \
-jar your-app.jar⚠️ From Java 9 onward the unified flag -Xlog:gc* is preferred, but the above syntax remains useful for Java 8 compatibility.
Parameter explanation
-Xloggc:gc.log: write GC logs to gc.log. -XX:+PrintGCDetails: output detailed GC information. -XX:+PrintGCDateStamps: include timestamps. -XX:+PrintHeapAtGC: show heap state before/after each GC. -XX:+PrintGCApplicationConcurrentTime: log application concurrent time. -XX:+PrintGCApplicationStoppedTime: log pause time.
Reading GC logs
Minor GC log example
2025-01-15T10:30:15.123+0800: 12.345: [GC (Allocation Failure)
2025-01-15T10:30:15.123+0800: 12.345: [DefNew: 5120K->512K(5888K), 0.0156 secs]
5120K->1024K(18880K), 0.0158 secs]
[Times: user=0.02 sys=0.00, real=0.02 secs]Timestamp : 2025-01-15T10:30:15.123+0800 GC reason : Allocation Failure (Eden space exhausted)
Young generation change : 5120K→512K (total 5888K) Overall heap change : 5120K→1024K (total 18880K) Duration : 0.0158 secs (≈15 ms)
Result: about 4.5 MB reclaimed, heap reduced from 5 MB to 1 MB.
Full GC log example
2025-01-15T10:35:22.456+0800: 345.678: [Full GC (Metadata GC Threshold)
2025-01-15T10:35:22.456+0800: 345.678: [CMS: 10240K->8192K(20480K), 0.4567 secs]
15360K->8192K(26368K), [Metaspace: 1024K->1024K(2048K)], 0.4570 secs]
[Times: user=0.45 sys=0.01, real=0.46 secs]Frequent Full GC indicates old‑generation or Metaspace pressure.
Duration > 1 s severely impacts response time.
"Metadata GC Threshold" shows Metaspace exhaustion (many classes loaded).
No heap reduction after GC suggests a possible memory leak.
Key GC metrics and health thresholds
Minor GC frequency: < 1 ×/min (healthy) → > 10 ×/min (high risk).
Full GC frequency: < 1 ×/day (healthy) → > 5 ×/day (high risk).
Single GC pause: < 50 ms (good) → > 200 ms (danger).
Post‑GC memory growth: < 5 % (acceptable) → > 20 % (critical).
Common GC algorithms comparison
Serial – suitable for single‑core CPUs and small heaps (<1 GB). Enabled with -XX:+UseSerialGC.
Parallel – for multi‑core machines where throughput matters. Enabled with -XX:+UseParallelGC.
CMS – low‑latency, medium heaps (4‑16 GB). Concurrent collection, higher CPU cost. Enabled with -XX:+UseConcMarkSweepGC.
G1 – large heaps (>4 GB) with predictable pauses. Region‑based collection. Enabled with -XX:+UseG1GC.
ZGC – ultra‑large heaps (>16 GB) with sub‑millisecond pauses (Java 11+). Enabled with -XX:+UseZGC.
GC log visualization tools
GCViewer – open‑source, offline analysis.
GCEasy – online, visual, free; no installation required.
Arthas – Alibaba open‑source tool for real‑time production diagnostics.
GCViewer usage example
# Download GCViewer
wget https://github.com/chewiebug/GCViewer/releases/download/1.38/gcviewer-1.38-SNAPSHOT.jar
# Analyze the GC log
java -jar gcviewer-1.38-SNAPSHOT.jar gc.logPractical patterns for locating memory problems
Memory‑leak GC pattern
# Memory‑leak GC pattern
[GC (Allocation Failure) 1024M->1023M(2048M), 2.3 secs]
[GC (Allocation Failure) 1024M->1024M(2048M), 2.5 secs]
[GC (Allocation Failure) 1025M->1025M(2048M), 2.8 secs]Characteristics: post‑GC memory hardly decreases and GC pause time keeps growing.
High‑pressure GC pattern
# Frequent GC with unchanged reclamation
[GC 512M->256M(1024M), 0.05 secs] # every 10 s
[GC 512M->256M(1024M), 0.05 secs]
[GC 512M->256M(1024M), 0.05 secs]Characteristics: GC runs very often but each run reclaims the same amount of memory.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Coder Trainee
Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
