Detecting Virtual Thread Pinning in Java

Virtual threads represent a significant leap forward for Java. I believe they will rejuvenate the language. Combined with all the recent advancements, this will further solidify Java's dominance in areas where it already leads, such as enterprise software.
I was aware that Java 21 had issues with thread pinning when entering a synchronized block. To verify whether this problem has been resolved in Java 24, I needed a way of knowing if a thread is pinned and used the following jvm flag: -Djdk.tracePinnedThreads=full This flag should help track if virtual threads still get pinned.
For testing purposes, we have this basic code:
private static final Object lock = new Object();
public static void main(String[] args) {
Thread virtualThread = Thread.ofVirtual().start(() -> {
synchronized (lock) {
System.out.println("vt");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
}
When running it with Java 21, I got the following log:
Virtual thread is pinned inside synchronized block
Thread[#22,ForkJoinPool-1-worker-1,5,CarrierThreads]
java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:183)
java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
java.base/java.lang.VirtualThread.parkNanos(VirtualThread.java:621)
java.base/java.lang.VirtualThread.sleepNanos(VirtualThread.java:791)
java.base/java.lang.Thread.sleep(Thread.java:507)
playground.thread.Echo.lambda$main$0(Echo.java:21) <== monitors:1
java.base/java.lang.VirtualThread.run(VirtualThread.java:309)
When running the same code with Java 24, no pinning occurs. While I understand it can still happen when calling native code, for most use cases the issue is gone.

