Fundamentals 17 min read

JVM Initialization Deadlock Analysis and Resolution

This article investigates a production thread‑pool exhaustion issue caused by a JVM class‑initialization deadlock, explains the underlying class‑loading mechanics, presents detailed stack‑trace analysis, and offers a preventive solution with early bean initialization and a reproducible demo.

JD Tech
JD Tech
JD Tech
JVM Initialization Deadlock Analysis and Resolution

During a production deployment, an alarm indicated that a JSF thread pool was exhausted on only one of thirty machines, leading to service interruption. Initial investigation ruled out traffic imbalance, long business processing times, and slow database access, pinpointing a concurrency lock in the application code.

The root cause was traced to the initialization of ProtoStuffSerializer , which failed on the problematic machine due to a deadlock during class loading. Multiple threads were stuck in the static initializer of RuntimeEnv and related classes ( IdStrategy , ExplicitIdStrategy ), each waiting for the other to complete initialization.

Analysis of JVM class‑initialization revealed that when a class’s <clinit> method is executed, the class state becomes being_initialized . If another thread attempts to initialize the same class concurrently, it must wait, leading to a deadlock when circular dependencies exist between static initializers of classes A and B.

To break the deadlock, the solution pre‑loads the critical classes by defining a bean that forces early initialization of the serializer factory, ensuring that the static blocks run before the thread pool is saturated.

A demonstration program reproduces the deadlock with two threads initializing classes A and B, each invoking the other's static method, causing both to wait on each other's <clinit> . The demo confirms the scenario and validates the early‑initialization fix.

In conclusion, class‑initialization deadlocks are subtle and can arise from circular static dependencies; developers should avoid such patterns and be cautious with default methods in interfaces that may trigger implicit class loading.

Recommended reading includes articles on JDK driver class initialization deadlocks, JVM initialization specifications, and common JVM commands.

[WARN]2023-04-10 18:03:34.847 [] |[JSF-23002]Task:java.util.concurrent.FutureTask@502cdfa0 has been reject for ThreadPool exhausted! pool:200, active:200, queue:0, taskcnt: 2159[BusinessPool#:][JSF-SEV-WORKER-225-T-8]
"JSF-BZ-22000-223-T-1" #980 daemon prio=5 os_prio=0 tid=0x00007fd164002000 nid=0x99a in Object.wait() [0x00007fd1de8b7000]
   java.lang.Thread.State: RUNNABLE
  at com.jd.purchase.utils.serializer.impl.ProtoStuffSerializer.
(ProtoStuffSerializer.java:42)
public class JVMTest {
    public static void main(String[] args) {
        new Thread(){
            public void run(){
                B.test();
            }
        }.start();
        new Thread(){
            public void run(){
                A.test();
            }
        }.start();
    }
}
class A{
    static{
        int a=0;
        System.out.println(a);
        B.test();
    }
    static void test(){
        System.out.println("调用了A的test方法");
    }
}
class B{
    static{
        int b=0;
        System.out.println(b);
        A.test();
    }
    static void test(){
        System.out.println("调用了B的test方法");
    }
}
JavaJVMConcurrencydeadlockThreadPoolClass Loading
JD Tech
Written by

JD Tech

Official JD technology sharing platform. All the cutting‑edge JD tech, innovative insights, and open‑source solutions you’re looking for, all in one place.

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.