Java Concurrency & Async Programming · Lesson 16

JVM Garbage Collection Logs and Pause Diagnosis Explained

Read Java 25 garbage collection logs to distinguish allocation pressure, live-set growth, concurrent work, pauses, and Full GC safely.

Quick answer

GC logs describe how one JVM allocates and reclaims managed heap; they do not directly measure user impact, process RSS, container termination, or durable business recovery. Read them as a timeline: collector and heap configuration, allocation rate, occupancy before and after comparable collections, pause type and duration, concurrent-cycle progress, promotion or relocation pressure, and any Full GC. Correlate that timeline with the Spring order service SLI, CPU, process memory, container events, dependencies, and version changes.

Java 25 unified logging can emit collector summaries and progressively deeper phase detail. Start with enough information to classify the symptom. Add tags or debug levels only for a bounded investigation because more output has storage, processing, and exposure costs.

Learning objectives

  • Interpret unified GC logs using allocation rate, live set, pause phases, concurrent cycles, and failure transitions instead of judging event frequency alone.
  • Decide whether evidence supports heap sizing, allocation reduction, collector-specific investigation, or a non-GC hypothesis.

Prerequisites

Start with Production JVM Performance Diagnostics and understand young and old object lifetimes at a conceptual level. Collector-specific decisions continue in the G1 and ZGC lessons.

Evidence and system boundary

A log line records a collector event under one JVM clock and configuration. Preserve JVM version, collector, heap limits, container memory and CPU, uptime, service version, traffic interval, and log rotation policy. An event duration may include stop-the-world work, concurrent work, or both depending on the message. Compare like event types before calculating trends.

This Java 25 command is an explanatory starting point, not a production configuration that was executed or approved:

java -Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags:filecount=8,filesize=32m -jar order-service.jar

Confirm supported tags with the selected runtime. Logging to a constrained container filesystem can create a new outage if rotation and storage are not bounded.

Read a collection timeline

Begin with the heap transition. Occupancy before collection shows managed heap pressure; occupancy after a comparable old-generation or whole-heap event approximates the retained live set, not the true application ownership of every object. A rising after-collection floor under comparable load is a leak hypothesis. A flat floor with a steep sawtooth points more strongly to allocation rate or a heap that is too small for the workload.

Separate pause time from concurrent time. G1 marking and ZGC relocation perform substantial work concurrently with application threads and can consume CPU without one long pause. Compare GC CPU, application throughput, request latency, allocation, and container throttling. A low pause percentile does not guarantee sufficient throughput.

Promotion or relocation pressure indicates that surviving objects and allocation demand are consuming old-generation or relocation headroom. A Full GC is a transition worth explaining, not a diagnosis by itself. Identify its cause, reclaimed space, duration, surrounding allocation, and whether repeated events approach an out-of-memory condition.

Use deeper phase logs only after the broad class is known. G1 phase logging can expose remembered-set scanning, root processing, object copy, reference processing, or evacuation trouble. ZGC logs can expose concurrent-cycle timing and allocation stalls. Collector-specific terms are not interchangeable.

Production failure scenario

After a Spring order service release, p99 latency rises for ten minutes. GC logs show the same pause durations as the previous version, but allocation per request and concurrent GC CPU increase sharply. The after-collection live set returns to its earlier range. Container CPU throttling also rises.

The evidence supports an allocation and CPU hypothesis, not a heap leak. The team compares allocation samples to the changed serialization path, canaries a rollback, and verifies request latency, CPU throttling, allocation, GC CPU, and durable order outcomes. It does not increase -Xmx merely to reduce collection frequency because that may delay the symptom while leaving allocation and CPU cost unchanged.

Common misconceptions

  • Frequent young collections are not automatically harmful; pause, CPU, throughput, and objectives determine impact.
  • Heap occupancy before a collection is not the retained live set.
  • A Full GC does not prove a memory leak or identify which objects are responsible.
  • Short pauses do not prove the collector has low total CPU cost.
  • GC logs cannot prove a container OOMKill, database recovery, or successful order commit.

Decision checklist

  • Record JDK update, collector, heap limits, CPU limits, uptime, and service version.
  • Align GC timestamps with user latency, traffic, deployment, and container evidence.
  • Compare allocation rate and after-collection occupancy under comparable load.
  • Separate stop-the-world pauses from concurrent collector CPU.
  • Explain every Full GC and allocation stall before changing flags.
  • Increase log detail only for a bounded question with rotation and access controls.
  • Prefer reducing wasteful allocation or fixing retention before compensating with heap.
  • Revalidate user outcomes and process memory after any collector or heap change.

Choose G1 Garbage Collector Diagnosis and Tuning for the default collector path or ZGC Low-Latency Diagnosis and Tuning for an explicitly selected low-latency collector. Follow the complete Java Concurrency course and its topic cluster.

Official sources

Official sources accessed August 19, 2026. Collector messages, defaults, and diagnostic options are version-sensitive and must be checked against the exact runtime in use.

Knowledge check

Check your understanding

Answer both questions correctly to mark this lesson as mastered. You can retry without penalty.

1. After-collection occupancy stays flat while allocation and concurrent GC CPU rise after a release; which hypothesis best fits the evidence?

2. Why can short GC pauses coexist with worse checkout latency?