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)
> 

Reply via email to