RFR (M) 8198313: Wrap holder object for ClassLoaderData in a WeakHandle

coleen.phillimore at oracle.com coleen.phillimore at oracle.com
Fri Mar 30 17:53:02 UTC 2018


I have an incremental and full .02 version with the changes discussed here.

open webrev at http://cr.openjdk.java.net/~coleenp/8198313.02.incr/webrev
open webrev at http://cr.openjdk.java.net/~coleenp/8198313.02/webrev

These have been retested on x86, all hotspot jtreg tests.
thanks,
Coleen

On 3/29/18 12:37 PM, coleen.phillimore at oracle.com wrote:
>
> Hi Kim,
> Thank you for reviewing this.
>
> On 3/28/18 5:12 PM, Kim Barrett wrote:
>>> On Mar 26, 2018, at 1:26 PM, coleen.phillimore at oracle.com wrote:
>>>
>>> Summary: Use WeakHandle for ClassLoaderData::_holder so that 
>>> is_alive closure is not needed
>>>
>>> The purpose of WeakHandle is to encapsulate weak oops within the 
>>> runtime code in the vm.  The class was initially written by 
>>> StefanK.   The weak handles are pointers to OopStorage. This code is 
>>> a basis for future work to move direct pointers to the heap (oops) 
>>> from runtime structures like the StringTable, into pointers into an 
>>> area that the GC efficiently manages, in parallel and/or concurrently.
>>>
>>> Tested with mach5 tier 1-5.  Performance tested with internal 
>>> dev-submit performance tests, and locally.
>>>
>>> open webrev at http://cr.openjdk.java.net/~coleenp/8198313.01/webrev
>>> bug link https://bugs.openjdk.java.net/browse/JDK-8198313
>>>
>>> Thanks,
>>> Coleen
>> ------------------------------------------------------------------------------ 
>>
>> src/hotspot/share/oops/weakHandle.cpp
>>
>>    59 void WeakHandle::release() const {
>>    60   Universe::vm_weak_oop_storage()->release(_obj);
>>
>> Is WeakHandle::release ever called with a handle that has not been
>> cleared by GC?  The only caller I found is ~ClassLoaderData.  Do we
>> ever construct a CLD with filled-in holder, and then decide we don't
>> want the CLD after all?  I'm thinking of something like an error
>> during class loading or the like, but without much knowledge.
>
> We call WeakHandle::release in ~ClassLoaderData only.  The oop is 
> always null.   There's a race when adding the ClassLoaderData to the 
> class_loader oop.  If we win this race, we create the WeakHandle. See 
> lines 982-5 of this change.
>
> I wanted to avoid creating the WeakHandle and destroying it if we lose 
> this race, so I did not create it in the ClassLoaderData constructor.
> I have a follow-on change that moves it there however.
>
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/hotspot/share/classfile/classLoaderData.cpp
>>    59 #include "gc/shared/oopStorage.hpp"
>>
>> Why is this include needed?  Maybe I missed something, but it looks
>> like all the OopStorage usage is wrapped up in WeakHandle.
>
> It is not needed, removed.
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/hotspot/share/oops/instanceKlass.cpp
>> 1903 void InstanceKlass::clean_implementors_list(BoolObjectClosure* 
>> is_alive) {
>> 1904   assert(class_loader_data()->is_alive(), "this klass should be 
>> live");
>> ...
>> 1909         if (!impl->is_loader_alive(is_alive)) {
>>
>> I'm kind of surprised we still need the is_alive closure here. But
>> there are no changes in is_loader_alive.  I think I'm not
>> understanding something.
>
> We do not need the is_alive closure here.   I have a follow on change 
> in my patch queue that removes these.
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/hotspot/share/classfile/classLoaderData.hpp
>>   224   oop _class_loader;          // oop used to uniquely identify 
>> a class loader
>>   225                               // class loader or a canonical 
>> class path
>>
>> [Not part of the change, but adjacent to one, so it caught my eye.]
>>
>> "class loader \n class loader" in the comment looks redundant?
>
> That was left over from the early days.  Rewrote as below.  I have a 
> change to remove this later too.
>
>   oop _class_loader;          // The instance of java/lang/ClassLoader 
> associated with
>                                         // this ClassLoaderData
>
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/hotspot/share/classfile/classLoaderData.cpp
>>   516   assert(_holder.peek() == NULL, "never replace holders");
>>
>> I think peek is the wrong test here.  Shouldn't it be _holder.is_null()?
>> If not, e.g. if !_holder.is_null() can be true here, then I think
>> that would be a leak when _holder is (re)assigned.
>>
>> Of course, this goes back to my earlier private comment that I find
>> WeakHandle::is_null() a bit confusing, because I keep thinking it's
>> about the value of *_handle._obj rather than _handle._obj.
>
> is_null() is for a holder that hasn't been set yet or is zero as for 
> the_null_class_loader_data().
>
> This case should definitely be is_null().
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/hotspot/share/classfile/classLoaderData.cpp
>>   632   bool alive = keep_alive()         // null class loader and 
>> incomplete anonymous klasses.
>>   633       || _holder.is_null()
>>   634       || (_holder.peek() != NULL);  // not cleaned by weak 
>> reference processing
>>
>> I was initially guessing that _holder.is_null() was for null class
>> loader and/or anonymous classes, but that's covered by the preceeding
>> keep_alive().  So I don't know why a null holder => alive.
>
> Yes, I believe it is redundant.   Or did I add it for a special case 
> that I can't remember.  I'll verify.
>
> Thanks,
> Coleen
>
>>
>> ------------------------------------------------------------------------------ 
>>
>>
>



More information about the hotspot-dev mailing list