A DESCRIPTION OF THE PROBLEM :
When running an application with pinned, blocked virtual threads AND an active javaagent, the application hangs. The issues was originally reported for the opentelemetry autoinstrumentation javaagent here: https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/10181
The issue can be forced to occur when starting the JVM with the `-Djdk.tracePinnedThreads=short` flag.
With the flag added, the JVM will hang immediately when a pinned virtual thread blocks (e.g. Thread.sleep).
Without the flag according to the original report on the opentelemetry-agent the application will eventually also hang, but it is harder to reproduce.
The hanging JVM is unresponsive, making this issue a bit hard to debug: An attached debugger won't be able to pause the JVM, the JVM will not respond to `jcmd` commands and `jfr` won't flush it's output in time to help with analysis.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Build a javaagent which just registeres an empty ClassFileTransformer
2. Run the provided sample Java application with `-Djdk.tracePinnedThreads=short` and the `-javaagent:` built from step 1 :
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The JVM terminates normally after printing "Done sleep"
ACTUAL -
The JVM hangs after printing "Entering sleep"
---------- BEGIN SOURCE ----------
Agent-Premain class:
```
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class AgentMain {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("Registering No-Op transformer");
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
return null;
}
});
}
}
```
Application Main Class:
```
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
Object lock = new Object();
executor.submit(() -> {
synchronized (lock) {
try {
System.out.println("Entering sleep");
Thread.sleep(100);
System.out.println("Done sleep ");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
}
}
}
```
---------- END SOURCE ----------
FREQUENCY : always