Ephemeral threads
Robert Engels
robaho at me.com
Thu Jan 8 18:33:58 UTC 2026
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 <alex at puredanger.com> 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)
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20260108/d9294027/attachment-0001.htm>
More information about the loom-dev
mailing list