loom-dev Digest, Vol 95, Issue 2
Xialin Liu
beef.liu at qq.com
Tue Nov 4 03:17:06 UTC 2025
Hi Patricio
In our scenario, we encountered a similar issue that appears to stem from the same root cause. I’m happy to share the case details.
The problem arises in our custom class loader: when we use Logback to log messages, Logback attempts to acquire a lock during write operations. Meanwhile, a virtual thread that’s in the process of class initialization gets pinned to its carrier thread. As a result, other virtual threads attempting to use the same class end up being blocked with the message:
"Waited for initialization of <class> by other thread".
These waiting threads also get pinned to their carrier threads — but crucially, they do not enter <clinit>. This creates a deadlock-like situation where:
One ForkJoinPool (FJP) worker thread is trying to acquire Logback’s lock.
Other FJP workers are waiting on a non-existent ObjectMonitor (likely due to the pinned thread holding the monitor and not progressing).
Interestingly, the stack traces appear to be in normal Java code, which makes the root cause non-obvious at first glance.
"ForkJoinPool-1-worker-28" #799 [828] daemon prio=5 os_prio=0 cpu=47855486.95ms elapsed=258235.59s allocated=42813G defined_classes=287 tid=0x00007f4803ad9000 nid=828 waiting on condition [0x00007fd88ee65000]
java.lang.Thread.State: WAITING (parking)
Carrying virtual thread #101393
at jdk.internal.vm.Continuation.run(java.base at 21.0.3.0.6.1-redjdk/Continuation.java:252)
- parking to wait for <0x00007f4892f23810> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.lang.VirtualThread.runContinuation(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:299)
at java.lang.VirtualThread$$Lambda/0x00007f484085cc48.run(java.base at 21.0.3.0.6.1-redjdk/Unknown Source)
at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(java.base at 21.0.3.0.6.1-redjdk/ForkJoinTask.java:1403)
at java.util.concurrent.ForkJoinTask.doExec(java.base at 21.0.3.0.6.1-redjdk/ForkJoinTask.java:387)
at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(java.base at 21.0.3.0.6.1-redjdk/ForkJoinPool.java:1313)
at java.util.concurrent.ForkJoinPool.scan(java.base at 21.0.3.0.6.1-redjdk/ForkJoinPool.java:1844)
at java.util.concurrent.ForkJoinPool.runWorker(java.base at 21.0.3.0.6.1-redjdk/ForkJoinPool.java:1809)
at java.util.concurrent.ForkJoinWorkerThread.run(java.base at 21.0.3.0.6.1-redjdk/ForkJoinWorkerThread.java:188)
"engine-44-111" #101393 Mounted virtual thread on "ForkJoinPool-1-worker-28" #799
at jdk.internal.misc.Unsafe.park(java.base at 21.0.3.0.6.1-redjdk/Native Method)
- parking to wait for <0x00007fd984009f38> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.lang.VirtualThread.parkOnCarrierThread(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:817)
at java.lang.VirtualThread.park(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:755)
at java.lang.System$2.parkVirtualThread(java.base at 21.0.3.0.6.1-redjdk/System.java:2714)
at java.util.concurrent.locks.LockSupport.park(java.base at 21.0.3.0.6.1-redjdk/LockSupport.java:221)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base at 21.0.3.0.6.1-redjdk/AbstractQueuedSynchronizer.java:754)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base at 21.0.3.0.6.1-redjdk/AbstractQueuedSynchronizer.java:990)
at java.util.concurrent.locks.ReentrantLock$Sync.lock(java.base at 21.0.3.0.6.1-redjdk/ReentrantLock.java:153)
at java.util.concurrent.locks.ReentrantLock.lock(java.base at 21.0.3.0.6.1-redjdk/ReentrantLock.java:322)
at ch.qos.logback.core.OutputStreamAppender.writeBytes(OutputStreamAppender.java:197)
at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:231)
at ch.qos.logback.core.rolling.RollingFileAppender.subAppend(RollingFileAppender.java:235)
at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:421)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.info(Logger.java:591)
at com.example.loader.PluginClassLoader.reverseLoadClassInternal(PluginClassLoader.java:217)
at com.example.loader.PluginClassLoader.loadClass(PluginClassLoader.java:132)
- locked <0x00007fd9b83dabc0> (a com.example.loader.SharedPluginClassLoader)
at java.lang.ClassLoader.loadClass(java.base at 21.0.3.0.6.1-redjdk/ClassLoader.java:526)
at com.example.MyExample.init(MyExample.java:34)
at com.example.TaskHelper$$Lambda/0x00007f484149dec0.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base at 21.0.3.0.6.1-redjdk/ThreadPoolExecutor.java:1144)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base at 21.0.3.0.6.1-redjdk/ThreadPoolExecutor.java:642)
at java.lang.Thread.runWith(java.base at 21.0.3.0.6.1-redjdk/Thread.java:1607)
at java.lang.VirtualThread.run(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:462)
at java.lang.VirtualThread$VThreadContinuation$1.run(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:254)
at jdk.internal.vm.Continuation.enter0(java.base at 21.0.3.0.6.1-redjdk/Continuation.java:326)
at jdk.internal.vm.Continuation.enter(java.base at 21.0.3.0.6.1-redjdk/Continuation.java:317)
"ForkJoinPool-1-worker-23" #786 [828] daemon prio=5 os_prio=0 cpu=55.73ms elapsed=51857.88s allocated=1659K defined_classes=6 tid=0x00007fd92f9de800 nid=828 in Object.wait() [0x00007fd88ef67000]
java.lang.Thread.State: RUNNABLE
Carrying virtual thread #1265
at jdk.internal.vm.Continuation.run(java.base at 21.0.3.0.6.1-redjdk/Continuation.java:255)
at java.lang.VirtualThread.runContinuation(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:299)
at java.lang.VirtualThread$$Lambda/0x00007fd93b7e4068.run(java.base at 21.0.3.0.6.1-redjdk/Unknown Source)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(java.base at 21.0.3.0.6.1-redjdk/ForkJoinTask.java:1423)
at java.util.concurrent.ForkJoinTask.doExec(java.base at 21.0.3.0.6.1-redjdk/ForkJoinTask.java:387)
at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(java.base at 21.0.3.0.6.1-redjdk/ForkJoinPool.java:1313)
at java.util.concurrent.ForkJoinPool.scan(java.base at 21.0.3.0.6.1-redjdk/ForkJoinPool.java:1844)
at java.util.concurrent.ForkJoinPool.runWorker(java.base at 21.0.3.0.6.1-redjdk/ForkJoinPool.java:1809)
at java.util.concurrent.ForkJoinWorkerThread.run(java.base at 21.0.3.0.6.1-redjdk/ForkJoinWorkerThread.java:188)
"arkhouyi-houyi-pool-3-5" #1265 Mounted virtual thread on "ForkJoinPool-1-worker-23" #786
at com.example.ExampleAccessor.getExample(ExampleAccessor.java:57)
at com.example.TaskHelper$$Lambda/0x00007fd93c47e4d8.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base at 21.0.3.0.6.1-redjdk/ThreadPoolExecutor.java:1144)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base at 21.0.3.0.6.1-redjdk/ThreadPoolExecutor.java:642)
at java.lang.Thread.runWith(java.base at 21.0.3.0.6.1-redjdk/Thread.java:1607)
at java.lang.VirtualThread.run(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:462)
at java.lang.VirtualThread$VThreadContinuation$1.run(java.base at 21.0.3.0.6.1-redjdk/VirtualThread.java:254)
at jdk.internal.vm.Continuation.enter0(java.base at 21.0.3.0.6.1-redjdk/Continuation.java:326)
at jdk.internal.vm.Continuation.enter(java.base at 21.0.3.0.6.1-redjdk/Continuation.java:317)
Xialin Liu
Original
From: loom-dev-request <loom-dev-request at openjdk.org>
Date: 2025-11-04 02:08
To: loom-dev <loom-dev at openjdk.org>
Subject: loom-dev Digest, Vol 95, Issue 2
Hi Danny,
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.
Thanks,
Patricio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20251104/0078dffe/attachment-0001.htm>
More information about the loom-dev
mailing list