Given this code, that tries to listen to the event jdk.VirtualThreadPinned
when a virtual thread is pinned:
import static org.junit.Assert.assertTrue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import jdk.jfr.Event;
import jdk.jfr.Name;
import jdk.jfr.consumer.RecordingStream;
import org.junit.Test;
public class JFRTest {
@Test
public void pinnedVirtualThreads() throws InterruptedException {
CountDownLatch stopListening = new CountDownLatch(1);
CountDownLatch startListening = new CountDownLatch(1);
try (RecordingStream recordingStream = new RecordingStream()) {
// Create and start the recording stream
startRecordingStream(recordingStream, startListening, stopListening);
// Make sure JFR listener is running before continue
while (true) {
new StartEvent().commit();
if (startListening.await(1, TimeUnit.SECONDS)) {
break;
}
}
// Simulate blocking operation
Thread vt = Thread.ofVirtual().start(() -> {
synchronized (this) {
System.out.println("Virtual Thread is pinned");
}
});
vt.join();
}
// Wait till the jdk.VirtualThreadPinned triggers
assertTrue("jdk.VirtualThreadPinned was not sent", stopListening.await(5, TimeUnit.SECONDS));
}
private void startRecordingStream(RecordingStream recordingStream, CountDownLatch startListening, CountDownLatch stopListening) {
// Enable the jdk.VirtualThreadPinned event
recordingStream.enable("jdk.VirtualThreadPinned").withStackTrace();
// Notify listener is running after receiving the StartEvent
recordingStream.onEvent("StartEvent", event -> {
System.out.println("Received " + event);
startListening.countDown();
});
// Set an event handler
recordingStream.onEvent("jdk.VirtualThreadPinned", event -> {
System.out.println("VirtualThreadPinned event detected!");
System.out.println("Timestamp: " + event);
stopListening.countDown();
});
// Start the recording stream
recordingStream.startAsync();
}
@Name("StartEvent")
private static class StartEvent extends Event {
}
}
This is the output:
Received StartEvent {
startTime = 10:15:32.723 (2024-06-12)
eventThread = "main" (javaThreadId = 1)
stackTrace = [
com.example.general.JFRTest.pinnedVirtualThreads() line: 25
jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Object, Object[]) line: 103
java.lang.reflect.Method.invoke(Object, Object[]) line: 580
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall() line: 59
org.junit.internal.runners.model.ReflectiveCallable.run() line: 12
]
}
Virtual Thread is pinned
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 6.211 s <<< FAILURE! - in com.example.general.JFRTest
As you can see, this part should trigger the event jdk.VirtualThreadPinned
, but it is not happening. On the other hand, the other event StartEvent
is caught:
Thread vt = Thread.ofVirtual().start(() -> {
synchronized (this) {
System.out.println("Virtual Thread is pinned");
}
});
I don’t know why.
This is my JDK version is: 21.0.3+7-LTS-152