Backend Development 6 min read

Diagnosing and Resolving a Java Process Memory Leak Using GC Logs and jmap

After observing a Java process with persistently high memory usage, the article details a step‑by‑step investigation using top, ps, GC logging, and jmap to identify a memory leak caused by a third‑party jar, and shows how adjusting JVM parameters and fixing the code resolved the issue.

360 Quality & Efficiency
360 Quality & Efficiency
360 Quality & Efficiency
Diagnosing and Resolving a Java Process Memory Leak Using GC Logs and jmap

Background A Java process was found to consume a large amount of memory continuously; restarting the process temporarily cleared the usage, but the problem reappeared after a while.

Investigation Process

1. Identify the high‑memory process ID using top .

2. Retrieve the startup command line with ps :

java -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -server -jar XXXXX-jar-with-dependencies.jar production

3. Add the GC logging parameters to the command line (as shown above).

4. Analyze the GC logs to observe memory changes in each generation.

The logs showed frequent Minor GCs, while the old generation and perm‑gen memory kept growing without significant reduction after CMS cycles.

5. Use jmap to inspect object distribution in the heap:

jmap -histo 3296 > test-jmap.txt

jmap -histo:live 3296 > test-jmap.txt

The histogram revealed a large number of objects from the package pdown , indicating a probable memory leak.

Decompiling the third‑party jar with JD‑GUI showed that a Task object was enqueued each time it was created and only removed during unInit . Because the queue is a static constant, failing to call unInit caused the objects to remain alive, leading to frequent GC and memory pressure.

6. Fix the code by invoking pdown.unInit() after use, which eliminated the leak.

Summary

1. Which Java objects can be reclaimed? The JVM uses reachability analysis starting from GC roots; objects not reachable from any root form an unreachable set and are eligible for collection.

2. CMS (Concurrent Mark‑Sweep) Collector

Features:

Targets the old generation.

Mark‑and‑sweep algorithm (no compaction, may cause fragmentation).

Concurrent and multithreaded, minimizing pause times.

Typical usage: ParNew + CMS + Serial Old for services with heavy user interaction, such as internet or B/S system back‑ends.

Key parameters:

-XX:+UseConcMarkSweepGC – enable CMS.

-XX:+UseCMSCompactAtFullCollection – compact after Full GC.

-XX:+CMSFullGCsBeforeCompaction – compact after a set number of Full GCs.

-XX:ParallelCMSThreads=<n> – number of CMS threads (usually equals CPU cores).

Drawbacks:

Highly sensitive to CPU resources.

Can produce fragmentation and “floating garbage”.

May encounter “Concurrent Mode Failure”.

Javabackend developmentmemory-leakCMSgcjmap
360 Quality & Efficiency
Written by

360 Quality & Efficiency

360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.