Fundamentals 5 min read

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.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Understanding Log4j2 High Concurrency Blocking and JVM Reflection Optimization

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 MyApp

References: https://rednaxelafx.iteye.com/blog/548536, https://blogs.oracle.com/buck/inflation-system-properties

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.

javaJVMperformanceconcurrencyReflectionlog4j2
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.