[External] : Re: Virtual thread memory leak because TrackingRootContainer keeps threads

robert engels robaho at icloud.com
Fri Aug 2 14:58:28 UTC 2024


Sorry to keep this thread going but in reviewing my test results I think this capability is now dangerous, as I related to the Thread.stop(). It is going to be the same issue. 

A lot of native resource backed objects have Java shadows with finalizers / reference queues. If the referenced are released without traveling up the stack the program/system can be in an inconsistent state. 

Take for instance a file system lock file that is removed on finalization. This would be removed allowing other processing to continue even though the locking process never completed nor rolled back.

Maybe you could argue it is a bad design to do this but I think the pattern with Cleaners, etc is fairly pervasive. 

By releasing the objects program order guarantees are broken - I don’t think it is valid to do this - especially concerning try/finally. 

As I also said you could maybe be very tricky and just release the memory but that isn’t what is happening here. It is collecting the objects which allows side effects through finalization and reference queues. 


> On Aug 1, 2024, at 11:39 PM, Robert Engels <rengels at ix.netcom.com> wrote:
> 
> Chance. Sorry mobile with old eyes.
> 
>> On Aug 1, 2024, at 5:21 PM, robert engels <robaho at icloud.com> wrote:
>> 
>> Absence of memory leaks means a better change of the lifecycle management being correct.
>> 
>>>> On Aug 1, 2024, at 4:55 PM, Ron Pressler <ron.pressler at oracle.com> wrote:
>>> 
>>> 
>>> 
>>>>> On 1 Aug 2024, at 20:04, Robert Engels <robaho at icloud.com> wrote:
>>>> 
>>>> 
>>>> I find memory leaks - or lack there of - a decent check of correctness. With this VT change, that will no longer be the case.
>>> 
>>> If you find memory leaks an aid to debugging, by all means track all of your threads.
>>> 
>>>> 
>>>> I also don’t like reviewing a piece of code - consumer() in this case - and having to determine if it is correct based on a system property value. This seems against Java’s explicitness (although I realize some system properties already alter behavior greatly).
>>> 
>>> It is not. Whether and when objects are collected is also subject to GC selection. One of the GCs in the JDK never collects any object.
>>> 
>>> But it seems to me that all you’re doing is using an implementation detail as an aid to debugging the code, and that’s fine.
>>> 
>>> 
>>>> 
>>>> As an aside, based on your previous comments, it is curious that the objects are not collected in A. It is in the same state as B - the system knows that queue.take() can never advance - so if the references are not being held by stack entries then they should be collected, right - regardless that a Thread is a GC root?
>>> 
>>> Let’s forget about roots. Roots are an implementation detail of the GC, and even the same GC can treat different objects as roots or not depending on the type of the collection. What matters is whether or not an object is reachable. Well, platform threads do happen to be roots and that’s why they’re always considered reachable, but that’s not the point. What matters to the purpose of understanding the behaviour is that all platform threads are always considered reachable.
>>> 
>>> Now, if a thread is reachable, it is much harder to prove that it is, indeed, stuck forever (e.g. you can obtain a reference to it and interrupt it). The simple proof that a thread is stuck forever is that it is blocked unreachable, because if it is unreachable it is neither currently scheduled nor can it ever be unblocked (or interrupted) because to unblock (or interrupt) a thread, you need a reference to it.
>>> 
>>> Because a platform thread is reachable, the VM cannot prove that it’s stuck forever, and so it assumes it could continue, and if it can continue, then it may access certain references on the stack, so they’ll be considered live.
>>> 
>>> — Ron


More information about the loom-dev mailing list