[External] : Re: Virtual thread memory leak because TrackingRootContainer keeps threads
Michal Domagala
outsider404 at gmail.com
Tue Jul 9 11:51:25 UTC 2024
Thanks for valuable observability context
As I understand, initially VT created by Thread API was not observable in
thread dump and VT created by Executors API was observable. It was
confusing and now both kinds of VT are observable. Make sense.
But observability is reached by strong reference. VT created by Thread API
are strongly referenced until stop and not GC'ed until stop and VT created
by Executors API are not referenced at all and GC'ed when not reachable,
regardless of being stopped or not. That's not OK and much worse than
previous confusion.
It is not clear to me if strongly-referenced-VT-created-from-Thread-API is
intentional or a mistake. Initially I thought it was a mistake caused by
lack of awareness of the VT lifecycle. However, it is written that "GC'ing
a thread that has not terminated will be very surprising to some
developers. (...) is the expected behavior. Virtual threads started
directly with the Thread API will be kept strongly reachable until they
terminate."
In my understanding observability != strongly referenced. Current
observability implementation, based on frail requirement that
created-from-API VT should be present in thread dump as other VT, caused
them to be strongly referenced, which is against JEP 444.
I am convinced that VT must not be strongly referenced, regardless of
whether the API was used for creation. However, if the opposite decision is
taken, it must be documented and published somewhere.
I would like to mention another clue that observability is implemented
without VT knowledge. When -Djdk.trackAllThreads=false, observability is
limited. Instead of strong references to VT
(TrackingRootContainer#VTHREADS) there is counter:
CountingRootContainer#VTHREAD_COUNT
Counter is increased by onStart() and decreased by onStop(). But some VTs
are gone without onStop(), so the counter is not properly decreased.
wt., 9 lip 2024 o 09:50 Alan Bateman <Alan.Bateman at oracle.com> napisał(a):
> On 08/07/2024 22:12, Michal Domagala wrote:
>
> Hi
>
> As a thread author, I would like to say I opened the thread because I
> could not report a memory leak as a bug. Page
> https://bugreport.java.com/bugreport/submit_start
> <https://urldefense.com/v3/__https://bugreport.java.com/bugreport/submit_start__;!!ACWV5N9M2RV99hQ!O3-6Y8rB_Q3TnOXLeIa2WkhSm-X8hYgCkqwGAG4EqpVKaFgdKdh4kpH4juXWBBVbkBbMxFZDjRsTawE7Yeih$>
> does not work.
>
> In my understanding JEP 444 is finished and delivered in JDK 21. Any
> deviation between JEP 444 and JDK 21 is a bug.
> I hoped somebody will say "OMG" and start fixing procedure. But it seems
> to me discussion concerns on JEP 444 - good or bad decision was taken.
>
> Personally, I have high confidence in the written word. Written word
> convinced me that VT is GC'ed. It's very interesting to see other opinions,
> but in my understanding the time is out of joint and seek for help to set
> it right
>
>
> The topic you brought up was an open question when virtual threads were a
> preview feature in JDK 19/20. For JDK 19/20, virtual threads created
> directly with the Thread API were only only kept strongly reachable when
> doing some operation that may continue (blocked on I/O, timer, ...). This
> meant that, in some cases, "abandoned" virtual threads could be GC'ed even
> though they had not terminated.
>
> The main thing that came up during the preview period was observability.
> There were several questions here as to why virtual threads created
> directly with the Thread API didn't show up in thread dumps. It was
> surprising when virtual threads in other thread groupings (e.g.
> Executors.newVirtualThreadPerTaskExecutor) did appear in the thread dump.
> This was part of the motivation to change things before virtual threads
> became a permanent feature (see the History section of JEP 444).
>
> Aside from observability, the other issue is that GC'ing a thread that has
> not terminated will be very surprising to some developers. In many cases it
> will be transparent but there are cases where it is more nuanced and can be
> observed in advanced usages. Finalization is one topic. Another is Cleaner
> actions that may run while a resource is in an inconsistent state.
>
> The summary is that the behavior you observe in JDK 21/22/23 is the
> expected behavior. Virtual threads started directly with the Thread API
> will be kept strongly reachable until they terminate. The thread dump and
> other observability support can be used to identify "abandoned" threads.
> This project has left the door open to the possibility of introducing some
> notion of "ephemeral threads" in the future. It would require quite a bit
> of exploration in several areas, would have to be opt-in, and would also
> require Finalization to be removed before introducing anything.
>
> -Alan
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20240709/bd6d93cd/attachment-0001.htm>
More information about the loom-dev
mailing list