<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div dir="ltr"></div><div dir="ltr">It is such a small piece of the problem though. Yes, potentially the system could detect that nothing could ever write to the queue and clean up everything - but there are two issues with that imo:</div><div dir="ltr"><br></div><div dir="ltr">1. When writing a queue reader you need to know the dynamics of what? That a read might result in termination of the thread with no additional code executed? I think it is better to use weak references to queues if you want something like this and perform and orderly shutdown. Much easier to read. </div><div dir="ltr"><br></div><div dir="ltr">2. The above may work in the queue case, but I suspect the vast majority of usage will be with sockets. There is no way to know that the socket will never see more data - unless it is closed. Better to create similar closable queues with similar usage patterns. </div><div dir="ltr"><br></div><div dir="ltr">Special casing this queue scenario seems like a very bad idea to me. </div><div dir="ltr"><br><blockquote type="cite">On Jul 2, 2024, at 9:46 AM, Michal Domagala <outsider404@gmail.com> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">I did research and I found that virtual threads are designed with the rule that RAM is the limit. It means millions of virtual threads are OK. And millions of GC roots is garbage collector death.<div><br></div><div>But it is a performance reason, not a "heart" reason. For me, the "heart" reason is simplicity of use. I would like to use virtual thread in any place in code when I want without overhead. For example, I can parallelize computation using just ForkJoinPool. I would like to parallelize blocking with the same simplicity. </div><div><br></div><div>One of Java's simplicity factors is the lack of destructor. When object reference is lost, I do not care how resources are reclaimed. If VT is not GC root, I can start as many as I want within - a potentially complex - object and the system will reclaim resources when the object is GC'ed. If VT is GC root, I must inspect each VT one by one and make sure they are stopped. </div><div>It is called a destructor and destructor is not simple.<br><br>People wrote here that platform and virtual threads should be interchangeable. They are interchangeable, because they have the same API. Being GC root is not API - it is implementation.<br> </div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">wt., 2 lip 2024 o 02:37 Brian S O'Neill <<a href="mailto:bronee@gmail.com" target="_blank">bronee@gmail.com</a>> napisał(a):<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I was confused when I first discovered that virtual threads could be <br>
GC'd when blocked with an infinite timeout. This was before the <br>
trackAllThreads option was enabled by default.<br>
<br>
If the virtual thread is blocked with an effectively infinite timeout <br>
(100 years), it won't be GC'd even when trackAllThreads is false. For <br>
consistency, I think it makes sense for virtual threads to never <br>
actually be GC'd except until after they exit.<br>
<br>
If you depended on virtual threads being GC'd when blocked with a real <br>
infinite timeout, then switching to platform threads would introduce a <br>
memory leak that didn't exist before. Ideally, the two thread types <br>
should be interchangeable.<br>
<br>
<br>
On 2024-07-01 12:08 PM, Michal Domagala wrote:<br>
> According to <a href="https://openjdk.org/jeps/444" rel="noreferrer" target="_blank">https://openjdk.org/jeps/444</a> <<a href="https://openjdk.org/jeps/444" rel="noreferrer" target="_blank">https://openjdk.org/jeps/444</a>>,<br>
> <br>
> "Unlike platform thread stacks, virtual thread stacks are not GC roots."<br>
> <br>
> But jdk.internal.vm.ThreadContainers.RootContainer.TrackingRootContainer#VTHREADS keeps (hard) references to each virtual thread. Effectively, virtual threads are GC roots.<br>
> <br>
> I described full example here: <br>
> <a href="https://stackoverflow.com/questions/78596905/why-virtual-thread-is-not-garbage-collected-when-not-reachable" rel="noreferrer" target="_blank">https://stackoverflow.com/questions/78596905/why-virtual-thread-is-not-garbage-collected-when-not-reachable</a> <<a href="https://stackoverflow.com/questions/78596905/why-virtual-thread-is-not-garbage-collected-when-not-reachable" rel="noreferrer" target="_blank">https://stackoverflow.com/questions/78596905/why-virtual-thread-is-not-garbage-collected-when-not-reachable</a>><br>
> <br>
> The problem was not visible since <br>
> <a href="https://bugs.openjdk.org/browse/JDK-8309406" rel="noreferrer" target="_blank">https://bugs.openjdk.org/browse/JDK-8309406</a> <br>
> <<a href="https://bugs.openjdk.org/browse/JDK-8309406" rel="noreferrer" target="_blank">https://bugs.openjdk.org/browse/JDK-8309406</a>>, because before the <br>
> change, VTHREADS "keep" was not enabled and i guess nobody cares memory <br>
> leak.<br>
> <br>
> But after the change every JVM is affected.<br>
> <br>
> A workaround for memory leak is set jdk.trackAllThreads=false<br>
> <br>
> Best regards<br>
> Michal Domagala<br>
> <br>
</blockquote></div>
</div></blockquote></body></html>