Understanding Log4j2 High Concurrency Blocking and JVM Reflection Optimization
The article explains how Log4j2 can cause thread blocking under heavy exceptions due to class‑loading locks, describes the JVM's reflection optimization mechanism, shows how to verify it with sample code, and outlines ways to disable or tune the optimization using system properties.
When using Log4j2 for logging, a large number of exceptions can cause many threads to block due to the way Log4j2 processes stack traces.
The problem originates from
org.apache.logging.log4j.core.impl.ThrowableProxy.toExtendedStackTrace, which performs class loading via ClassLoader.loadClass. The class loader acquires a lock, checks findLoadedClass, and may delegate loading according to the parent‑delegation model.
During reflective calls, the JVM generates synthetic classes named sun.reflect.GeneratedMethodAccessor<N> using an internal DelegatingClassLoader. These classes cannot be loaded by the application class loader, causing prolonged lock holding and thread blockage when many exceptions are logged.
JVM Reflection Optimization
The JVM provides two ways to perform reflection: JNI native calls and pure‑Java bytecode generation that creates sun.reflect.GeneratedMethodAccessor<N>. The pure‑Java path is slower on the first invocation but becomes much faster after several calls.
When a reflective method is invoked more than a threshold (default 15), the JVM switches from JNI to the pure‑Java implementation. The threshold can be controlled with the system property -Dsun.reflect.inflationThreshold=<value>, and the switch can be forced immediately with -Dsun.reflect.noInflation=true.
Verification Sample
The following Java program demonstrates the reflective call and can be used to observe the generated accessor class and its class loader.
public class TestMethodInvoke {
public static void main(String[] args) throws Exception {
Class<?> clz = Class.forName("A");
Object o = clz.newInstance();
Method m = clz.getMethod("foo", String.class);
for (int i = 0; i < 100; i++) {
m.invoke(o, Integer.toString(i));
}
}
} public class A {
public void foo(String name) {
System.out.println("Hello, " + name);
}
}Running the program with -Dsun.reflect.inflationThreshold=2147483647 forces the JVM to keep using the JNI path, effectively disabling the optimization.
How to Disable the Optimization
The JVM only offers the two system properties mentioned above; therefore the optimization cannot be completely turned off. Setting a very large value for inflationThreshold, such as Integer.MAX_VALUE, is the closest approach.
Example command:
$ java -Dsun.reflect.inflationThreshold=2147483647 MyAppReferences: https://rednaxelafx.iteye.com/blog/548536, https://blogs.oracle.com/buck/inflation-system-properties
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.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow 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.
