I mean, it sort of doesn't? Coroutines is a whole concept, Virtual Threads can in most cases just replace java.lang.Threads, which is how it's implemented in Javalin. We just swap out the OS Threads for Virtual Threads.
now that i think about it i'm pretty sure my guess is completely wrong. memory usage (and thus concurrent-inactives) might be similar, but i expect the virtual threads to be much more efficient.