4

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.

Java User
  • 43
  • 4

1 Answers1

2

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.

Kire Haglin
  • 6,569
  • 22
  • 27
  • 1
    Thanks a lot. You considered many aspects, even the ones I missed to mention in my question. Your clue regarding the threshold helped me. I was using JDK 21 early-access build for running the app and I was creating JFR recording from JMC. It has an option to enable virtual thread related events in the wizard. I did that too. But still the events were not visible. What helped me was the clue about threshold. It was 20 ms by default. Only after changing it to 0, I could see them. Looks like these events happen very fast and are not recorded as they don't pass the threshold. – Java User Aug 08 '23 at 21:28
  • I have some more questions and I am very curious about Virtual Threads related features in JMC, JFR, VisualVM. Do you know what is in the pipeline for JMC 9.0? What would be the best way to obtain such info? Thanks. – Java User Aug 08 '23 at 21:30
  • 1
    You might want to look at the JMC project page (https://wiki.openjdk.org/display/jmc/Main). It contains links to the JMC slack channel and mailing list. – Kire Haglin Aug 08 '23 at 23:57
  • Thanks for the comment. I did look through the JMC project page. There are many useful resources. The slack channel is limited to few organizations and I could not sign up there. But I have subscribed to the mailing list for JMC. Although I am not sure if this would be an appropriate question for the mailing list. I'll try nonetheless. – Java User Aug 11 '23 at 13:18