[External] : Re: Virtual thread memory leak because TrackingRootContainer keeps threads
Ron Pressler
ron.pressler at oracle.com
Mon Aug 5 03:42:58 UTC 2024
> On 4 Aug 2024, at 09:07, robert engels <robaho at icloud.com> wrote:
>
>
> So thank you, you provided the definitive answer that this ephemeral vt handling is not permitted.
>
Not only is it very much permitted, but collecting the thread makes no difference. The GC can and does collect objects that are guaranteed not to be accessed again, even on platform threads, and the GC collecting objects is not considered an “action generated by the thread” because it isn't. In other words, if a thread is blocked forever, all references on the stack are allowed to be collected, regardless of whether the thread itself is collected (BTW, even if it weren’t allowed by the spec, we can change the spec, although in this case it’s not needed).
I suggest you read the Javadoc for Reference.reachabilityFence, not so much because it makes things clear (it doesn’t at all), but because it highlights how subtle the behaviour is. These subtleties around reference queues are the least of their problems. Their biggest problem is that they simply don’t do what people think they’re supposed to do.
People think that reference queues are sort of an event the VM triggers when an object becomes unreachable (or shortly thereafter), but that is mostly a side effect of how the old GCs work, which made reference queues an approximation of that expectation. In actuality, the VM has no idea when an object becomes unreachable, and a reference is only enqueued if, by chance, the GC happens to decide to compact a certain region, at which point it will notice which objects in that region happen to be unreachable. With new GCs, the GC may never enqueue a reference for an object that’s become unreachable, or it may enqueue it hours after the fact.
In short, collecting stuck threads is consistent with the current spec and doing that is OK, Cleaners and reference queues are not okay in general, but if you must use them and accept that they don’t actually do what many think they do, you also need to be aware of various subtleties that necessitate reachability fences — and, as you’ll see, even reachabilityFence is tricky. Essentially, *if* the fence can be executed, then the reference won’t be dropped until after it’s executed. In other words, a rechabilityFence for a certain reference cannot be executed after the reference has been enqueued, but if the fence is never executed at all, well, then it says nothing about whether or not the reference can be enqueued. There’s a subtle but important difference between "X will not happen after Y" and “X must happen before Y”.
Since you seem to be concerned about different behaviour depending on implementation details, you should consider reference queues to be fundamentally useless even without their subtleties, and they’re becoming increasingly useless even in practice with new GCs and expected future GCs.
In any event, I think this conversation has run its course. The discussion of how useful reference queues are if at all, when if ever they can and should be used, and how unintuitive their behaviour can be given that even in the best conditions reference queues should be avoided, is an interesting one, but this is neither the time nor the place.
— Ron
More information about the loom-dev
mailing list