<div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">Thank you Vincente for looking at it.</div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"><br></div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">Just to be extra clear and not let you reflect on a non-problem, the "something behaving like a queue" is one of our internal classes. We are very satisfied with it, we have no intention of changing it.</div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">And we know that the best way to avoid leaks with this structure is to avoid retaining references to the nodes. So, in a sense, storing them as fields in a CountedCompleter is a risk. We though that it was a small risk as the completer would be GC soon after its execution. And it happens that cases exist where it is not.</div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">The obvious fix for us it clean the completers once their job is done. It is just massive, but meh, if we have to, we will do it.</div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"><br></div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">The sharing is mostly because it can impact many over codebases, beyond ours, possibly even Loom.</div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"><br></div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">Cheers</div><div style="font-family: Arial, sans-serif; font-size: 14px; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">Olivier</div><div class="protonmail_quote">
        Le samedi 29 novembre 2025 à 15:21, Vicente Pader <vicente.pader@gmail.com> a écrit :<br>
        <blockquote class="protonmail_quote" type="cite">
            <div dir="auto">Hi Olivier,</div><div dir="auto">Appreciate sharing your initiative with us. In my understanding of your case - </div><div dir="auto"><br></div><div dir="auto"><div dir="auto">“something that behaves like a concurrent linked queue (or a lock-free stack, or a tree of work items) where new work items are dynamically linked together via object references.”</div><div dir="auto"><br></div><div dir="auto">Let me know if this is reflective of your case.</div><div dir="auto"><br></div><div dir="auto">Cheers,</div><div dir="auto">Vince</div><br></div><div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sat, Nov 29, 2025 at 6:48 AM Olivier Peyrusse <<a href="mailto:kineolyan@protonmail.com" rel="noreferrer nofollow noopener">kineolyan@protonmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div style="font-family:Arial,sans-serif;font-size:14px"><span style="font-family:Arial,sans-serif">Hello community,<span style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif"><br></span></span><br><span style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif">Sorry if this is the wrong place to discuss internal classes such as the ForkJoinPool. If so, please, excuse me and point me in the right direction.</span></span><div style="font-family:Arial,sans-serif"></div></span><div style="font-family:Arial,sans-serif"><br></div><div style="font-family:Arial,sans-serif">At my company, we have experienced an unfortunate memory leak because one of our CountedCompleter was retaining a large object and the task was not released to the GC (I will give more details below but will first focus on the FJP code causing the issue).</div><div style="font-family:Arial,sans-serif"><br></div><div style="font-family:Arial,sans-serif">When running tasks, the FJP ends up calling <a href="https://github.com/openjdk/jdk/blob/c419dda4e99c3b72fbee95b93159db2e23b994b6/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java#L1448-L1453" title="WorkQueue#topLevelExec" rel="noreferrer nofollow noopener" target="_blank" style="font-family:Arial,sans-serif">WorkQueue#topLevelExec</a>, which is implemented as follow:</div><div style="font-family:Arial,sans-serif"><br></div><div style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif">        final void topLevelExec(ForkJoinTask<?> task, int fifo) {</span><div style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif">            while (task != null) {</span></div><div style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif">                task.doExec();</span></div><div style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif">                task = nextLocalTask(fifo);</span></div><div style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif">            }</span></div><span style="font-family:Arial,sans-serif">        }</span><br></div><div style="font-family:Arial,sans-serif"><span style="font-family:Arial,sans-serif"><br></span></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">We can see that it starts from a top-level task </font><code style="font-family:monospace">task</code><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">​, executes it, and looks for the next task to execute before repeating this loop. This means that, as long as we find a task through </font><code style="font-family:monospace">nextLocalTask</code>​<code style="font-family:monospace"></code><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">​, we do not exit this method and the caller of <code style="font-family:monospace">topLevelExec</code>​ retains in its stack a reference to the first executed task - like <a href="https://github.com/openjdk/jdk/blob/c419dda4e99c3b72fbee95b93159db2e23b994b6/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java#L1992-L2019" title="here" rel="noreferrer nofollow noopener" target="_blank" style="font-family:Arial,sans-serif">here</a>. This acts as a path from the GC root, preventing the garbage collection of the task.<br>So even if a CountedCompleter did complete its exec / tryComplete / etc, the framework will keep the object alive.</font></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">Could the code be changed to avoid this issue? I am willing to do the work, as well as come up with a test case reproducing the issue if it is deemed needed.</font></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)"><br></font></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">In our case, we were in the unfortunate situation where our counted completer was holding an element which happened to be a sort of head of a dynamic sort of linked queue. By retaining it, the rest of the growing linked queue was also retained in memory, leading to the memory leak.<br>Obvious fixes are possible in our code, by ensuring that we nullify such elements when our operations complete, and more ideas. But this means that we have to be constantly careful about the fields we pass to the task, what is captured if we give lambdas, etc. If the whole ForkJoinPool could also be improved to avoid such problems, it would be an additional safety.</font></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)"><br></font></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">Thank you for reading the mail</font></div><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">Cheers</font></div></div><div style="font-family:Arial,sans-serif;font-size:14px"><div style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)"><br></font></div><span style="font-family:Arial,sans-serif"><font face="Arial, sans-serif" style="font-family:Arial,sans-serif;color:rgb(0,0,0)">Olivier</font></span><br></div>
<div style="font-family:Arial,sans-serif;font-size:14px">
    <div style="font-family:Arial,sans-serif"></div>

            <div style="font-family:Arial,sans-serif">

            </div>
</div>
</blockquote></div></div>

        </blockquote><br>
    </div>