Search code examples
javajfrjmcvirtual-threads

Why does JMC (JDK Mission Control) not show any virtual thread events?


I have a small SpringBoot app with 1 RestController with following method:

    @GetMapping("/current-thread")
    String currentThread() throws InterruptedException {
        var msg = new Msg();
        Thread.startVirtualThread(() -> {
                    msg.s += Thread.currentThread().toString();
            }
        ).join();
        msg.s += Thread.currentThread().toString();
        return msg.s;
    }

The Msg class is just String wrapper:

    static class Msg{
        String s = new String();
    }

When I run the app and execute following curl command

curl localhost:8081/current-thread

I do get this output:

VirtualThread[#63]/runnable@ForkJoinPool-1-worker-1Thread[#38,http-nio-8081-exec-1,5,main]

This means the app is working fine. With every request it is creating a virtual thread.

But when I monitor this via JFR (JDK Flight Recorder) and check the recording via JMC (Java Mission Control), I do see the platform threads viz., http-nio and ForkJoinPool-worker threads. But I do not see any trace of the virtual thread. It does not show any virtual thread related events: No virtual thread events in JMC. I expected it to show 1 event of VirtualThreadstart and 1 of VirtualThreadEnd. I tried building JMC locally from source. But I do see the same problem.

My questions:

  • Is there something that I am missing?
  • Is this functionality not working in JMC? (I used JMC 8.3.1 and also built a version 9.0 locally from source.)
  • Is there a workaround?

Thanks.


Solution

  • Virtual Threads is still a preview feature in JDK 20, which means the virtual threads specific events are experimental and not shown in the JMC GUI by default.

    Also, some virtual thread specific events, like Virtual Thread Start and Virtual Thread End, are disabled by default to avoid flooding the buffers. A user could potentially start millions of virtual threads in a short period of time.

    You can download JDK 21 early-access builds, where the events are no longer experimental, and enable them on command-line:

    $ java -XX:StartFlightRecording:
        jdk.VirtualThreadStart#enabled=true,
        jdk.VirtualThreadEnd#enabled=true,
        filename=recording.jfr ...
    

    Events that happen in a virtual thread, for example the Socket Read event, should been seen without additional options, assuming the duration exceeds 20 ms (the default threshold). They will however not been seen in the Thread Graph page in JMC. It only displays platform threads.