<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Hi Danny,<br>
    <br>
    I see a couple of FJP workers that don’t seem to be carrying a
    virtual thread blocked on clinit. Do you have the full stacktraces?
    If available, the native stack traces would also be useful to verify
    the entry point into the VM for the ones blocked at clinit.<br>
    <br>
    Thanks,<br>
    Patricio<br>
    <br>
    <div class="moz-cite-prefix">On 11/2/25 9:44 PM, Danny Thomas wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAABjz10cEfmG5qqGHDDjseWzxxdzOXd6SWbB1d_Qws1qN-1sEQ@mail.gmail.com">
      
      <div dir="ltr">
        <div class="gmail_quote gmail_quote_container">
          <div dir="ltr">Hi folks,
            <div><br>
              We saw a clinit deadlock with Log4j 2 and virtual threads
              recently. It's common for libraries to use a mix of static
              and instance field loggers, so seems particularly
              vulnerable to this kind of deadlock at startup.<br>
              <br>
              I don't recall reading what you have planned for clinit
              pinning, so thought I'd pass on this potentially common
              real-world deadlock and ask what you have in mind for
              addressing this limitation.<br>
              <br>
              Cheers,<br>
              Danny<br>
              <br>
              Pinned virtual thread holding the clinit lock:<br>
              <br>
              #265
              "_internalWorkflowEvaluationQueue_2-workflow-evaluation-worker-0"
              virtual<br>
                    java.base/jdk.internal.misc.Unsafe.park(Native
              Method)<br>
                   
java.base/java.lang.VirtualThread.parkOnCarrierThread(VirtualThread.java:675)<br>
                   
              java.base/java.lang.VirtualThread.park(VirtualThread.java:607)<br>
                   
              java.base/java.lang.System$2.parkVirtualThread(System.java:2643)<br>
                   
              java.base/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:54)<br>
                   
java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:219)<br>
                   
java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:754)<br>
                   
java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1079)<br>
                   
java.base/java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock.java:738)<br>
                   
org.apache.logging.log4j.core.util.internal.InternalLoggerRegistry.getLogger(InternalLoggerRegistry.java:113)<br>
                   
org.apache.logging.log4j.core.util.internal.InternalLoggerRegistry.computeIfAbsent(InternalLoggerRegistry.java:196)<br>
                   
org.apache.logging.log4j.core.LoggerContext.getLogger(LoggerContext.java:588)<br>
                   
org.apache.logging.log4j.core.LoggerContext.getLogger(LoggerContext.java:561)<br>
                   
org.apache.logging.log4j.core.LoggerContext.getLogger(LoggerContext.java:71)<br>
                   
org.apache.commons.logging.LogAdapter$Log4jLog.<init>(LogAdapter.java:159)<br>
                   
org.apache.commons.logging.LogAdapter$Log4jAdapter.createLog(LogAdapter.java:113)<br>
                   
              org.apache.commons.logging.LogAdapter.createLog(LogAdapter.java:95)<br>
                   
              org.apache.commons.logging.LogFactory.getLog(LogFactory.java:67)<br>
                   
              org.apache.commons.logging.LogFactory.getLog(LogFactory.java:59)<br>
                   
org.springframework.data.redis.connection.convert.Converters.<clinit>(Converters.java:69)<br>
                   
org.springframework.data.redis.connection.DefaultStringRedisConnection.<init>(DefaultStringRedisConnection.java:187)<br>
                   
org.springframework.data.redis.connection.DefaultStringRedisConnection.<init>(DefaultStringRedisConnection.java:171)<br>
              <br>
              Unparked but unmounted virtual thread that's next in line
              for read lock:<br>
              <br>
              #369
              "_internalWorkflowEvaluationQueue_1-workflow-evaluation-worker-11"
              virtual<br>
                   
              java.base/java.lang.VirtualThread.park(VirtualThread.java:596)<br>
                   
              java.base/java.lang.System$2.parkVirtualThread(System.java:2643)<br>
                   
              java.base/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:54)<br>
                   
java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:219)<br>
                   
java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:754)<br>
                   
java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1079)<br>
                   
java.base/java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock.java:738)<br>
                   
org.apache.logging.log4j.core.util.internal.InternalLoggerRegistry.getLogger(InternalLoggerRegistry.java:113)<br>
                   
org.apache.logging.log4j.core.util.internal.InternalLoggerRegistry.computeIfAbsent(InternalLoggerRegistry.java:196)<br>
                   
org.apache.logging.log4j.core.LoggerContext.getLogger(LoggerContext.java:588)<br>
                   
org.apache.logging.log4j.core.LoggerContext.getLogger(LoggerContext.java:561)<br>
                   
org.apache.logging.log4j.core.LoggerContext.getLogger(LoggerContext.java:71)<br>
                   
org.apache.commons.logging.LogAdapter$Log4jLog.<init>(LogAdapter.java:159)<br>
                   
org.apache.commons.logging.LogAdapter$Log4jAdapter.createLog(LogAdapter.java:113)<br>
                   
              org.apache.commons.logging.LogAdapter.createLog(LogAdapter.java:95)<br>
                   
              org.apache.commons.logging.LogFactory.getLog(LogFactory.java:67)<br>
                   
              org.apache.commons.logging.LogFactory.getLog(LogFactory.java:59)<br>
                   
org.springframework.data.redis.connection.AbstractRedisConnection.<init>(AbstractRedisConnection.java:38)<br>
              <br>
              With the core workers all taken up by threads blocked on
              clinit, preventing the continuation for the unparked
              thread from running:<br>
              <br>
              "ForkJoinPool-2-worker-1" #266 [1606] daemon prio=5
              os_prio=0 cpu=233.52ms elapsed=2547.44s
              tid=0x00007fe9f38b4000 nid=1606 waiting on condition
               [0x00007fe9ccde6000]<br>
                 java.lang.Thread.State: WAITING (parking)<br>
                 at
              jdk.internal.misc.Unsafe.park(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Native">java.base@21.0.7.0.101/Native</a>
              Method)<br>
                 - parking to wait for  <0x0000040009f6d730> (a
              java.util.concurrent.ForkJoinPool)<br>
              --<br>
              "ForkJoinPool-2-worker-2" #267 [1607] daemon prio=5
              os_prio=0 cpu=393.88ms elapsed=2547.44s
              tid=0x00007fe9cdbf8000  [0x00007fe9cc465000]<br>
                 Carrying virtual thread #357<br>
                 at
jdk.internal.vm.Continuation.run(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Continuation.java:251">java.base@21.0.7.0.101/Continuation.java:251</a>)<br>
                 - waiting on the Class initialization monitor for
              org.springframework.data.redis.connection.convert.Converters<br>
              --<br>
              "ForkJoinPool-2-worker-3" #271 [1610] daemon prio=5
              os_prio=0 cpu=308.69ms elapsed=2547.43s
              tid=0x00007fe9cdbf8700  [0x00007fe9cc2e2000]<br>
                 Carrying virtual thread #367<br>
                 at
jdk.internal.vm.Continuation.run(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Continuation.java:251">java.base@21.0.7.0.101/Continuation.java:251</a>)<br>
                 - waiting on the Class initialization monitor for
              org.springframework.data.redis.connection.convert.Converters<br>
              --<br>
              "ForkJoinPool-2-worker-4" #272 [1611] daemon prio=5
              os_prio=0 cpu=428.92ms elapsed=2547.43s
              tid=0x00007fe9f5efdf00  [0x00007fe9cc261000]<br>
                 Carrying virtual thread #297<br>
                 at
jdk.internal.vm.Continuation.run(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Continuation.java:251">java.base@21.0.7.0.101/Continuation.java:251</a>)<br>
                 - waiting on the Class initialization monitor for
              org.springframework.data.redis.connection.convert.Converters<br>
              --<br>
              "ForkJoinPool-2-worker-5" #273 [1612] daemon prio=5
              os_prio=0 cpu=347.62ms elapsed=2547.42s
              tid=0x00007fe9cbef7000 nid=1612 waiting on condition
               [0x00007fe9cbee0000]<br>
                 java.lang.Thread.State: WAITING (parking)<br>
                 at
              jdk.internal.misc.Unsafe.park(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Native">java.base@21.0.7.0.101/Native</a>
              Method)<br>
                 - parking to wait for  <0x0000040009f6d730> (a
              java.util.concurrent.ForkJoinPool)<br>
              --<br>
              "ForkJoinPool-2-worker-6" #316 [1651] daemon prio=5
              os_prio=0 cpu=286.41ms elapsed=2547.04s
              tid=0x00007fe9db2f2000  [0x00007fe9ca6c5000]<br>
                 Carrying virtual thread #265<br>
                 at
jdk.internal.vm.Continuation.run(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Continuation.java:251">java.base@21.0.7.0.101/Continuation.java:251</a>)<br>
                 at
java.lang.VirtualThread.runContinuation(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/VirtualThread.java:245">java.base@21.0.7.0.101/VirtualThread.java:245</a>)<br>
              --<br>
              "ForkJoinPool-2-worker-7" #317 [1652] daemon prio=5
              os_prio=0 cpu=415.34ms elapsed=2547.03s
              tid=0x00007fe9db2f2700 nid=1652 waiting on condition
               [0x00007fe9ca645000]<br>
                 java.lang.Thread.State: WAITING (parking)<br>
                 at
              jdk.internal.misc.Unsafe.park(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Native">java.base@21.0.7.0.101/Native</a>
              Method)<br>
                 - parking to wait for  <0x0000040009f6d730> (a
              java.util.concurrent.ForkJoinPool)<br>
              --<br>
              "ForkJoinPool-2-worker-8" #359 [1675] daemon prio=5
              os_prio=0 cpu=108.86ms elapsed=2546.41s
              tid=0x00007fe9f58fff00  [0x00007fe9c9a69000]<br>
                 Carrying virtual thread #270<br>
                 at
jdk.internal.vm.Continuation.run(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Continuation.java:251">java.base@21.0.7.0.101/Continuation.java:251</a>)<br>
                 - waiting on the Class initialization monitor for
              org.springframework.data.redis.connection.convert.Converters<br>
              --<br>
              "ForkJoinPool-2-worker-9" #360 [1676] daemon prio=5
              os_prio=0 cpu=199.56ms elapsed=2546.41s
              tid=0x00007fea12c4ed00  [0x00007fe9c99e8000]<br>
                 Carrying virtual thread #363<br>
                 at
jdk.internal.vm.Continuation.run(<a class="moz-txt-link-abbreviated" href="mailto:java.base@21.0.7.0.101/Continuation.java:251">java.base@21.0.7.0.101/Continuation.java:251</a>)<br>
                 - waiting on the Class initialization monitor for
              org.springframework.data.redis.connection.convert.Converters<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>