<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">But even if VT threads are not GC roots, a GC root must have a reference to them, right? (to the Loom team) Otherwise they would be immediately collected.<div class=""><br class=""></div><div class="">If there is a reference to them, then that must follow up to a GC root (the static VT map), meaning that GC will still need to start from that root when tracing. I assume there could be low-level optimizations, where if a VT thread hasn’t run since the last GC, there is no need to follow it’s references because they could not have changed - but what if one of these references on its stack was a WeakReference? This would need clean-up since the clean-up handler might cause the VT or another to become Runnable.</div><div class=""><br class=""></div><div class="">TL;DR; It feels to me that VT threads not being GC roots doesn’t matter - as something must hold a strong reference - but I suspect I am missing something.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jul 22, 2024, at 4:51 PM, Michal Domagala <<a href="mailto:outsider404@gmail.com" class="">outsider404@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div dir="ltr" class=""><div dir="ltr" class=""><div dir="ltr" class=""><div class="">Thanks for the explanation.<br class=""><br class="">I understand that paragraph</div><div class=""><br class=""></div><div class="">"Unlike platform thread stacks, virtual thread stacks are not GC roots. Thus the references they contain are not traversed in a stop-the-world pause by garbage collectors, such as G1, that perform concurrent heap scanning"</div><div class=""><br class=""></div><div class="">can be rewritten as</div><div class=""><br class=""></div><div class="">"Some GC, such as G1, marks GC roots in stop-the-world pause. Unlike platform thread stacks, virtual thread stacks are not GC roots, therefore they do not impact stop-the-world pause."</div><div class=""><br class=""></div><div class="">In my opinion, the current paragraph in JEP 444 requires readers to have a deep GC background. Usually, developers are not aware of GC root cost (at least I was not aware). Developers could tune the number of GC roots by changing the number of platform threads. Others, like static variables, are rather not tunable.<br class="">But usually, the OS limits the number of platform threads much more strictly than GC performance.</div><div class=""><br class=""></div><div class="">To sum up, JEP 444's message is: "Do not be afraid of the G1 initial mark phase when using virtual threads". But I think most developers, like me, never heard about it. Ohers, more advanced, could also never care about it, because Oracle docs says about the initial mark phase: "This phase is piggybacked on a normal (STW) young garbage collection.". I understand this sentence as the phase is "for free".</div><div class=""><br class=""></div><div class="">To sum up again: when a developer like me reads that VT is not GC root, he does not see G1 profit behind. He reads: VT is GC'able. And the current state, when behavior is different, is misleading.</div><div class=""><br class=""></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">sob., 13 lip 2024 o 14:57 Ron Pressler <<a href="mailto:ron.pressler@oracle.com" class="">ron.pressler@oracle.com</a>> napisał(a):<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br class="">
<br class="">
> On 11 Jul 2024, at 19:40, Michal Domagala <<a href="mailto:outsider404@gmail.com" target="_blank" class="">outsider404@gmail.com</a>> wrote:<br class="">
> <br class="">
> Where is the mistake in my reasoning?<br class="">
>  <br class="">
<br class="">
All objects in the heap, including virtual thread stacks, are traversed by the GC. GC *roots*, however, are things that some GCs, G1 in particular, traverse *in a stop-the-world-pause* while they don’t walk non-root objects in a STW pause but concurrently with the application running. Furthermore, roots are kept in memory even if there are no strong references to them, while normal objects are kept only if there are strong references to them.<br class="">
<br class="">
Virtual threads, unlike platform threads, are regular heap objects rather than roots. This makes a difference to *when* they are scanned by the GC, which has an impact on GC performance, especially as there can be lots and lots of virtual threads. Additionally, *if* there is no strong reference to the virtual thread, the GC may collect it, but I pointed out that usually there is a strong reference that is kept by default for observability purposes, but you can change that option so that such a reference is not kept.<br class="">
<br class="">
— Ron</blockquote></div></div></div></div></div>
</div></blockquote></div><br class=""></div></body></html>