<html class="apple-mail-supports-explicit-dark-mode"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div dir="ltr"></div><div dir="ltr">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. </div><div dir="ltr"><br><blockquote type="cite">On Jan 8, 2026, at 11:49 AM, Alex Miller <alex@puredanger.com> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"><span id="gmail-docs-internal-guid-dcdf91a7-7fff-0594-ea29-4439c3c32cd1"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">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 (</span><a href="https://bugs.openjdk.org/browse/JDK-8309406" style="text-decoration-line:none"><span style="font-size:11pt;font-family:Arial,sans-serif;background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;text-decoration-line:underline;vertical-align:baseline">https://bugs.openjdk.org/browse/JDK-8309406</span></a>).<span style="background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);vertical-align:baseline"> It seems the notion of explicit ephemeral threads has been considered as a possible feature in the past to bring that back (</span><a href="https://mail.openjdk.org/pipermail/loom-dev/2024-July/006892.html" style="text-decoration-line:none"><span style="font-size:11pt;font-family:Arial,sans-serif;background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;text-decoration-line:underline;vertical-align:baseline">https://mail.openjdk.org/pipermail/loom-dev/2024-July/006892.html</span></a><span style="background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);vertical-align:baseline">).</span></p><br><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">In Clojure, we released a CSP/Go-like system called core.async way back in 2013 (</span><a href="https://clojure.github.io/core.async/rationale.html" style="text-decoration-line:none"><span style="font-size:11pt;font-family:Arial,sans-serif;background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;text-decoration-line:underline;vertical-align:baseline">https://clojure.github.io/core.async/rationale.html</span></a><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">). 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.</span></p><br><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">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.</span></p><br><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">However, due to virtual thread tracking</span><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline"> 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.</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:Arial,sans-serif;font-size:11pt"><br></span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:Arial,sans-serif;font-size:11pt">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.</span></p><br><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">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.</span></p><br><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline">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.</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);background-color:transparent;font-variant-numeric:normal;font-variant-east-asian:normal;font-variant-alternates:normal;vertical-align:baseline"><br></span></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><font color="#000000" face="Arial, sans-serif"><span style="font-size:14.6667px">Thanks for your consideration,</span></font></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><font color="#000000" face="Arial, sans-serif"><span style="font-size:14.6667px">Alex Miller (Clojure team)</span></font></p></span><br class="gmail-Apple-interchange-newline"></div>
</div></blockquote></body></html>