<div dir="auto"><div dir="auto">Hi Danny,</div><div dir="auto"><br></div>I have recently read <a href="https://bugs.openjdk.org/browse/JDK-8369238">https://bugs.openjdk.org/browse/JDK-8369238</a> shared by others, which could be relevant<div dir="auto"><br></div><div dir="auto">Hope that helped,</div><div dir="auto">Franz</div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">Il lun 3 nov 2025, 03:45 Danny Thomas <<a href="mailto:dannyt@netflix.com">dannyt@netflix.com</a>> ha scritto:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><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(java.base@21.0.7.0.101/Native 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(java.base@21.0.7.0.101/Continuation.java:251)<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(java.base@21.0.7.0.101/Continuation.java:251)<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(java.base@21.0.7.0.101/Continuation.java:251)<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(java.base@21.0.7.0.101/Native 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(java.base@21.0.7.0.101/Continuation.java:251)<br> at java.lang.VirtualThread.runContinuation(java.base@21.0.7.0.101/VirtualThread.java:245)<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(java.base@21.0.7.0.101/Native 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(java.base@21.0.7.0.101/Continuation.java:251)<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(java.base@21.0.7.0.101/Continuation.java:251)<br> - waiting on the Class initialization monitor for org.springframework.data.redis.connection.convert.Converters<br></div></div>
</div></div>
</blockquote></div>