Fundamentals 8 min read

Why Full GC Hits Metaspace Threshold and How to Resolve It

The article analyzes a recurring Full GC warning caused by Metaspace reaching its threshold, explains the underlying JVM mechanics, investigates dynamically generated reflection classes and SoftReference behavior, and provides a practical tuning solution by adjusting SoftRefLRUPolicyMSPerMB.

Programmer DD
Programmer DD
Programmer DD
Why Full GC Hits Metaspace Threshold and How to Resolve It

Problem Overview

Our newly deployed system occasionally raised alerts for Full GC durations exceeding 1 second. The GC logs (see image) showed the trigger reason as Metadata GC Threshold , meaning Metaspace had reached its configured limit.

Monitoring Metaspace usage over time revealed large fluctuations instead of the expected stable pattern.

Metaspace Basics

Metaspace stores class metadata; its size grows with the number of loaded classes. It resides in off‑heap memory and is only limited by the physical RAM. Two important JVM options are:

-XX:MetaspaceSize -XX:MaxMetaspaceSize
-XX:MetaspaceSize

defines the threshold that triggers a Full GC when Metaspace usage exceeds it; the value is adjusted dynamically after each GC. -XX:MaxMetaspaceSize sets the absolute upper bound.

A class can be unloaded only if:

All its instances have been reclaimed;

The class loader that loaded it has been reclaimed;

No live references to its java.lang.Class object exist.

Investigation Process

Examining the GC logs after a Full GC showed a significant drop in used Metaspace (e.g., 372620K → 158348K), indicating many classes were unloaded. This suggested the system was generating a large number of short‑lived classes.

We enabled class loading/unloading tracing: -XX:TraceClassLoading -XX:TraceClassUnloading The Tomcat logs then displayed many entries for classes named sun.reflect.GeneratedSerializationConstructorAccessorXXX. These classes are created by the JVM to accelerate reflective calls after they have been invoked repeatedly.

Reflection‑Generated Classes and SoftReferences

When reflection is used extensively (e.g., by Spring or Dubbo), the JVM generates helper classes and holds them via SoftReference . A SoftReference is reclaimed only when memory is low; otherwise it remains.

The JVM decides whether to keep a SoftReference based on three factors:

How long the object has not been accessed (current clock minus timestamp);

Available free heap space;

The constant SoftRefLRUPolicyMSPerMB (default 1000 ms per MB of free space).

The decision formula is:

clock - timestamp <= freespace * SoftRefLRUPolicyMSPerMB

In our environment -XX:SoftRefLRUPolicyMSPerMB=0 was set, causing SoftReferences to be reclaimed almost immediately, which forced the JVM to regenerate the reflection helper classes repeatedly, inflating Metaspace usage.

Solution

We changed the parameter to a larger value, e.g., -XX:SoftRefLRUPolicyMSPerMB=6000. After the change, Metaspace usage stabilized and Full GC alerts stopped appearing.

References

[1] 假笨说 – 从一起GC血案谈到反射原理: https://mp.weixin.qq.com/s/5H6UHcP6kvR2X5hTj_SBjA?

[2] Java的强引用、软引用、弱引用、虚引用及其使用场景: http://blogxin.cn/2017/09/16/java-reference/

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.

Javajvm-tuningMetaspaceFull GCSoftReference
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.