Why My Spring Boot App Swallowed 7 GB RAM: Uncovering Native Memory Leaks

After migrating a project to the MDP framework based on Spring Boot, the author observed excessive swap usage and physical memory consumption of 7 GB despite a 4 GB heap limit, and through a series of JVM, system, and native‑code diagnostics identified Spring Boot’s ZipInflaterInputStream native‑memory leak caused by unchecked package scanning.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why My Spring Boot App Swallowed 7 GB RAM: Uncovering Native Memory Leaks

Background

To better manage a project, the team migrated a module to the MDP framework (based on Spring Boot). Soon the system repeatedly reported high swap usage. Although the JVM was configured with a 4 GB heap, the process consumed up to 7 GB of physical memory, which was abnormal.

JVM options used:

-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+AlwaysPreTouch -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m -Xss512k -Xmx4g -Xms4g -XX:+UseG1GC -XX:G1HeapRegionSize=4M

Top command showed the memory usage.

Top memory usage
Top memory usage

Investigation Process

1. Locate memory at the Java level

Added -XX:NativeMemoryTracking=detail and restarted the service. jcmd <pid> VM.native_memory detail displayed the distribution of native memory, showing that the committed memory reported by the command was smaller than the physical usage because it does not include native allocations made by C code.

jcmd native memory
jcmd native memory

Using pmap revealed many 64 MB address ranges that were not listed by jcmd, suggesting native allocations.

pmap memory
pmap memory

2. Locate native memory at the system level

Since Java‑level tools could not pinpoint the culprit, system tools were used.

gperftools

gperftools profiling showed a peak of about 3 GB allocated via malloc, then dropping to 700‑800 MB.

gperftools
gperftools

The pattern suggested that memory was allocated with mmap/brk rather than malloc.

strace

Running strace -f -e brk,mmap,munmap -p <pid> captured the memory‑request system calls but did not reveal suspicious allocations during normal operation.

strace
strace

Repeating the trace while the application started showed many 64 MB mmap regions, matching the earlier pmap output.

strace during startup
strace during startup

jstack

Using the thread IDs from strace, jstack <pid> identified the threads that performed the large mmap calls.

jstack thread
jstack thread

The culprit turned out to be the Meituan Configuration Center (MCC) which uses Reflections to scan all JAR packages. The scanning process invokes Spring Boot’s ZipInflaterInputStream, which uses Inflater (native code) to decompress JARs and allocates off‑heap memory that is only released by the finalizer.

btrace stack
btrace stack

After configuring MCC to scan only specific packages, the memory problem disappeared.

3. Why the off‑heap memory was not released

Spring Boot wraps InflaterInputStream but does not explicitly free the native memory; it relies on the Inflater finalizer. In the observed version, the finalizer was not triggered promptly, and the underlying glibc memory allocator kept the freed pages in per‑thread arenas (64 MB each), so the OS memory usage remained high.

Updating to Spring Boot 2.0.5, which adds an explicit close() to ZipInflaterInputStream, resolves the issue.

Conclusion

The excessive native memory consumption was caused by MCC’s unrestricted package scanning, which caused Spring Boot’s ZipInflaterInputStream to allocate large off‑heap buffers that were only released by GC finalization. Upgrading Spring Boot or limiting the scan path eliminates the leak, and understanding the interaction between the JVM, native allocators, and glibc arenas is essential for diagnosing similar memory‑usage anomalies.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMmemory leakSpring BootNative Memorygperftools
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

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.