ClassValue rooting objects after it goes away?
Charles Oliver Nutter
headius at headius.com
Fri Mar 2 20:22:52 UTC 2018
Put it another way: does a static reference from a class to itself prevent
that class from being garbage collected? Of course not. ClassValue is
intended to be a way to inject pseudo-static data into either a class or a
Class. Injecting that data, even if it has a reference back to the class,
should not prevent the class from being collected.
On Fri, Mar 2, 2018 at 2:19 PM Charles Oliver Nutter <headius at headius.com>
wrote:
> I have posted a modified version of my description to the main bug report.
>
> TLDR: ClassValue should not root objects.
>
> - Charlie
>
> On Fri, Mar 2, 2018 at 2:13 PM Charles Oliver Nutter <headius at headius.com>
> wrote:
>
>> Yes, it may be the same bug.
>>
>> In my case, the ClassValue is held by a utility object used for our Java
>> integration. That utility object has to live somewhere, so it's held by the
>> JRuby runtime instance. There's a strong reference chain leading to the
>> ClassValue.
>>
>> The value is a Ruby representation of the class, with reflected methods
>> parsed out and turned into Ruby endpoints. Obviously, the value also
>> references the class, either directly or indirectly through reflected
>> members.
>>
>> The Ruby class wrapper is only hard referenced directly if there's an
>> instance of the object live and moving through JRuby. It may be referenced
>> indirectly through inline caches.
>>
>> However...I do not believe this should prevent collection of the class
>> associated with the ClassValue.
>>
>> The value referenced in the ClassValue should not constitute a hard
>> reference. If it is alive *only* because of its associate with a given
>> class, that should not be enough to root either the object or the class.
>>
>> ClassValue should work like ThreadLocal. If the Thread associated with a
>> value goes away, the value reference goes away. ThreadLocal does nothing
>> prevent it from being collected. If the Class associated with a Value goes
>> away, the same should happen to that Value and it should be collectable
>> once all other hard references are gone.
>>
>> Perhaps I've misunderstood?
>>
>> - Charlie
>>
>> On Fri, Mar 2, 2018 at 12:16 PM Vladimir Ivanov <
>> vladimir.x.ivanov at oracle.com> wrote:
>>
>>> Charlie,
>>>
>>> Does it look similar to the following bugs?
>>> https://bugs.openjdk.java.net/browse/JDK-8136353
>>> https://bugs.openjdk.java.net/browse/JDK-8169425
>>>
>>> If that's the same (and it seems so to me [1]), then speak up and
>>> persuade Paul it's an important edge case (as stated in JDK-8169425).
>>>
>>> Best regards,
>>> Vladimir Ivanov
>>>
>>> [1] new RubyClass(Ruby.this) in
>>>
>>> public static class Ruby {
>>> private ClassValue<RubyClass> cache = new
>>> ClassValue<RubyClass>() {
>>> protected RubyClass computeValue(Class<?> type) {
>>> return new RubyClass(Ruby.this);
>>> }
>>> };
>>>
>>> On 3/1/18 2:25 AM, Charles Oliver Nutter wrote:
>>> > So I don't think we ever closed the loop here. Did anyone on the JDK
>>> > side confirm this, file an issue, or fix it?
>>> >
>>> > We still have ClassValue disabled in JRuby because of the rooting
>>> issues
>>> > described here and in https://github.com/jruby/jruby/pull/3228.
>>> >
>>> > - Charlie
>>> >
>>> > On Thu, Aug 27, 2015 at 7:04 AM Jochen Theodorou <blackdrag at gmx.org
>>> > <mailto:blackdrag at gmx.org>> wrote:
>>> >
>>> > One more thing...
>>> >
>>> > Remi, I tried your link with my simplified scenario and it does
>>> there
>>> > not stop the collection of the classloader
>>> >
>>> > Am 27.08.2015 11:54, schrieb Jochen Theodorou:
>>> > > Hi,
>>> > >
>>> > > In trying to reproduce the problem outside of Groovy I stumbled
>>> > over a
>>> > > case case which I think should work
>>> > >
>>> > > public class MyClassValue extends ClassValue {
>>> > > protected Object computeValue(Class type) {
>>> > > Dummy ret = new Dummy();
>>> > > Dummy.l.add (this);
>>> > > return ret;
>>> > > }
>>> > > }
>>> > >
>>> > > class Dummy {
>>> > > static final ArrayList l = new ArrayList();
>>> > > }
>>> > >
>>> > > basically this means there will be a hard reference on the
>>> ClassValue
>>> > > somewhere. It can be in a static or non-static field, direct or
>>> > > indirect. But this won't collect. If I put for example a
>>> > WeakReference
>>> > > in between it works again.
>>> > >
>>> > > Finally I also tested to put the hard reference in a third class
>>> > > instead, to avoid this self reference. But it can still not
>>> collect.
>>> > >
>>> > > So I currently have the impression that if anything holds a hard
>>> > > reference on the class value that the classloader cannot be
>>> collected
>>> > > anymore.
>>> > >
>>> > > Unless I misunderstand something here I see that as a bug
>>> > >
>>> > > bye blackdrag
>>> > >
>>> >
>>> >
>>> > --
>>> > Jochen "blackdrag" Theodorou
>>> > blog: http://blackdragsview.blogspot.com/
>>> >
>>> > _______________________________________________
>>> > mlvm-dev mailing list
>>> > mlvm-dev at openjdk.java.net <mailto:mlvm-dev at openjdk.java.net>
>>> > http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>> >
>>> > --
>>> >
>>> > - Charlie (mobile)
>>> >
>>> >
>>> >
>>> > _______________________________________________
>>> > mlvm-dev mailing list
>>> > mlvm-dev at openjdk.java.net
>>> > http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>> >
>>>
>> --
>>
>> - Charlie (mobile)
>>
> --
>
> - Charlie (mobile)
>
--
- Charlie (mobile)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20180302/a3ad596d/attachment.html>
More information about the mlvm-dev
mailing list