Isn’t this as simple as using weak references at the stdlib level to track the virtual threads? I’m surprised this isn’t the case already.
> On Jan 8, 2026, at 11:49 AM, Alex Miller <[email protected]> wrote: > > > I’d like to discuss adding support for ephemeral threads in the API. I know > virtual threads were originally ephemeral but before the Java 21 release > virtual thread tracking was added for observability > (https://bugs.openjdk.org/browse/JDK-8309406). It seems the notion of > explicit ephemeral threads has been considered as a possible feature in the > past to bring that back > (https://mail.openjdk.org/pipermail/loom-dev/2024-July/006892.html). > > In Clojure, we released a CSP/Go-like system called core.async way back in > 2013 (https://clojure.github.io/core.async/rationale.html). This system is > implemented via inversion of control and does parking on channel (queue) > operations via code rewriting. Core.async go blocks are ephemeral - they are > represented as data, referred to by channels when the go block is parked > waiting to put or take data on those channels. If all of the channels a go > block may be waiting on are GC’ed, the go block is GC’ed as it can never run > again. > > We have ported core.async to use virtual threads as it provides a superset of > the blocking/parking semantics we need (other than ephemerality). There are > many benefits to this change - no more code rewriting, lighter-weight > handoffs, extended parking support for I/O operations, etc. We would love to > make this switch. > > However, due to virtual thread tracking the ephemeral thread patterns our > users have relied on for more than a decade now result in go blocks being > strongly tracked even when unreachable, which creates memory leaks. Setting > -Djdk.trackAllThreads=false does what we want, but we are uneasy about > relying on undocumented flags that could change or go away. > > I understand the history of this change with respect to observability, and > the expectation that existing Java users are used to ensuring that threads > complete. Unlike Java users, our Clojure core.async users DO expect to be > able to safely abandon go blocks when all of their channels are no longer > reachable - we’ve been doing that for a long time. > > Virtual threads open the possibility of new Erlang-like architectures. > Ephemeral threads importantly enable lightweight process *library* > development as these new patterns can be composed without needing to handle > the termination concerns. core.async e.g. provides pub/sub, multiplexing, > pipelining and various other bits of non-trivial plumbing as libraries. Most > of those run as infinite loops to which user code maintains no enduring > references. There is simply no way to build such libraries on an old-school > approach to process termination. > > Given where things stood at Java 21 time and where we are now, can we move > the idea of ephemeral thread support forward? This is very important to us > and we are happy to get involved with the process and contribute if that > would be helpful. > > Thanks for your consideration, > Alex Miller (Clojure team) >
