RFR 8178604: JVM does not allow defining boot loader modules in exploded build after module system initialization

harold seigel harold.seigel at oracle.com
Tue May 9 13:14:21 UTC 2017


Hi David,

See comments embedded below.

Thanks, Harold


On 5/8/2017 8:52 PM, David Holmes wrote:
> Hi Harold,
>
> On 9/05/2017 4:00 AM, harold seigel wrote:
>> Hi David,
>>
>> Please see this updated webrev:
>> http://cr.openjdk.java.net/~hseigel/bug_8178604.3/webrev/index.html
>>
>> It contains the changes you requested below.
>
> Thank you. I will point out that Lois originally suggested the same 
> changes.
>
>> Note that the _exploded_entries table gets created very early during
>> SystemDictionary initialization, before initializing the pre-loaded
>> classes.  So, the code in load_class() at line ~1503 can assume that
>> _exploded_entries is not null.
>
> Which thread executes ClassLoader::add_to_exploded_build_list, and 
> which thread executes load_class() first? If they are guaranteed to be 
> the same thread then you don't need locking on the construction. If 
> they can be different threads then there must be some synchronization 
> between them that ensures _exploded_entries is properly visible after 
> construction.
They are the same thread.  At startup, the thread calls 
SystemDictionary::initialize_preloaded_classes(), which calls 
ClassLoader::classLoader_init2(), which calls add_to_exploded_build_list().

Control then returns back to 
SystemDictionary::initialize_preloaded_classes() which eventually calls 
SystemDictionary::load_instance_class(), which calls 
ClassLoader::load_class().   Here's the call stack showing these calls:

    V  [libjvm.so+0x974c0c] ClassLoader::load_class(Symbol*, bool,
    Thread*)+0x41c
    V  [libjvm.so+0x1648339]
    SystemDictionary::load_instance_class(Symbol*, Handle, Thread*)+0x819
    V  [libjvm.so+0x1648e25]
    SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle,
    Handle, Thread*)+0x985
    V  [libjvm.so+0x16494ba] SystemDictionary::resolve_or_null(Symbol*,
    Handle, Handle, Thread*)+0x5a
    V  [libjvm.so+0x16498fe] SystemDictionary::resolve_or_fail(Symbol*,
    Handle, Handle, bool, Thread*)+0x1e
    V  [libjvm.so+0x1649aa9]
    SystemDictionary::initialize_wk_klass(SystemDictionary::WKID, int,
    Thread*)+0x149
    V  [libjvm.so+0x1649bfe]
    SystemDictionary::initialize_wk_klasses_until(SystemDictionary::WKID,
    SystemDictionary::WKID&, Thread*)+0x5e
    V  [libjvm.so+0x1649dba] 
    SystemDictionary::*initialize_preloaded_classes*(Thread*)+0xea
    V  [libjvm.so+0x164a28a] SystemDictionary::initialize(Thread*)+0x26a
    V  [libjvm.so+0x16cd7e0]  Universe::genesis(Thread*)+0x7c0
    V  [libjvm.so+0x16ce4cc]  universe2_init()+0x2c
    V  [libjvm.so+0xe0f268]  init_globals()+0xa8
    V  [libjvm.so+0x1696e6f]  Threads::create_vm(JavaVMInitArgs*,
    bool*)+0x2df
                                 ...

So, is the existing synchronization in this change sufficient?

Thanks, Harold
>
> Thanks,
> David
> -----
>
>> Thanks, Harold
>>
>> On 5/4/2017 5:32 PM, David Holmes wrote:
>>> Hi Harold,
>>>
>>> On 5/05/2017 3:47 AM, harold seigel wrote:
>>>> Hi,
>>>>
>>>> Please review this updated webrev:
>>>>
>>>> http://cr.openjdk.java.net/~hseigel/bug_8178604.2/webrev/index.html
>>>>
>>>> The updated webrev takes out a lock when creating 
>>>> _exploded_entries.  It
>>>> also contains additional comments and an assert() to address Lois's
>>>> concerns with reduced code readability involving what situations 
>>>> warrant
>>>> taking out a lock in ClassLoader::search_module_entries().
>>>>
>>>> I don't think there needs to be two different initial entry points as
>>>> suggested by David below.  The method behaves slightly differently
>>>> depending on the value of its 'need_lock' parameter.  But, there is
>>>> enough common code for it to remain one method.
>>>
>>> I think this highlights uncertainty about the concurrent behaviour in
>>> relation to this code. On the one hand you are worried about an
>>> initialization race and so use the lock, but when you do:
>>>
>>> 1500       // The exploded build entries can be added to at any time
>>> so pass 'true' for
>>> 1501       // need_lock so that a lock is taken out when searching 
>>> them.
>>> 1502       assert(_exploded_entries != NULL, "No exploded build
>>> entries present");
>>> 1503       stream = search_module_entries(_exploded_entries,
>>> class_name, file_name, true, CHECK_NULL);
>>>
>>> you load _exploded_entries with no lock held and so must be certain
>>> that you can not possibly read a null value here.
>>>
>>> The needs_lock parameter seems superfluous - you know the condition
>>> for locking is that the list is the _exploded_entries, and you assert
>>> that. So no need to pass in needs_lock, just grab the lock when
>>> dealing with _exploded_entries.
>>>
>>> Cheers,
>>> David
>>>
>>>> Thanks, Harold
>>>>
>>>> On 5/3/2017 12:59 AM, David Holmes wrote:
>>>>> On 3/05/2017 7:11 AM, Lois Foltan wrote:
>>>>>> On 5/2/2017 9:03 AM, harold seigel wrote:
>>>>>>> Hi Lois,
>>>>>>>
>>>>>>> Thanks for your comments.  Please see my in-line responses.
>>>>>>>
>>>>>>> Harold
>>>>>>>
>>>>>>>
>>>>>>> On 5/1/2017 4:14 PM, Lois Foltan wrote:
>>>>>>>> Hi Harold,
>>>>>>>>
>>>>>>>> Looks good. A couple of comments:
>>>>>>>>
>>>>>>>> src/share/vm/classfile/classLoader.cpp
>>>>>>>>     line #828 - please take out the Module_lock when the
>>>>>>>> _exploded_entries is created
>>>>>>> This fix does not change the possible need for synchronization when
>>>>>>> _exploded_entries gets created during module system initialization.
>>>>>>> Are you saying that the existing code is wrong and should have 
>>>>>>> taken
>>>>>>> out the Module_lock before creating _exploding_entries?
>>>>>>
>>>>>> The method ClassLoader::add_to_exploded_build_list can be called at
>>>>>> anytime (during module system initialization and post module system
>>>>>> initialization).  Thus it seems prudent that no matter what the
>>>>>> current
>>>>>> JVM phase, that any access to ClassLoader::_exploding_entries be
>>>>>> protected via a lock.  That includes creation as well as insertion
>>>>>> into
>>>>>> the list.
>>>>>
>>>>> If creation is not guaranteed to occur before other threads that will
>>>>> call the same method and use the _exploded_entries list, then
>>>>> synchronization of some form is essential. If it is guaranteed 
>>>>> then we
>>>>> don't need create time sync just to be prudent - but the guarantee
>>>>> must be firmly established and clearly documented.
>>>>>
>>>>>>>
>>>>>>>>     line #1402 - I like the new factored out method
>>>>>>>> find_first_module_cpe(), however, instead of adding a new
>>>>>>>> "need_lock"
>>>>>>>> parameter, I would rather see code
>>>>>>>>                          in find_first_module_cpe() that takes the
>>>>>>>> Module_lock if the module_list parameter equals
>>>>>>>> ClassLoader::_exploded_entries
>>>>>>> I think your suggestion makes the code less flexible and does not
>>>>>>> require potential future callers of search_module_entries() to 
>>>>>>> think
>>>>>>> about synchronization.  So, I'd prefer to leave that change as is.
>>>>>>
>>>>>> I see your point.  My point was based on reduced code 
>>>>>> readability, the
>>>>>> further away from the decision to establish the lock, the less
>>>>>> apparent
>>>>>> it is within the new method ClassLoader::find_first_module_cpe() 
>>>>>> as to
>>>>>> what situations warranted the lock in the first place.
>>>>>
>>>>> Further, this:
>>>>>
>>>>> 1495       stream = search_module_entries(_exploded_entries,
>>>>> class_name, file_name, true, CHECK_NULL);
>>>>>
>>>>> is potentially unsafe if we can race with creation because we first
>>>>> access _exploded_entries without holding any lock! And the fact the
>>>>> method needs to do different things depending on which "list" was
>>>>> passed in suggests to me it should be two different initial entry
>>>>> points.
>>>>>
>>>>> Thanks,
>>>>> David
>>>>> -----
>>>>>
>>>>>> Thanks,
>>>>>> Lois
>>>>>>
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Lois
>>>>>>>>
>>>>>>>> On 5/1/2017 3:36 PM, harold seigel wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> Please review this JDK-10 bug fix to allow defining of modules to
>>>>>>>>> the boot loader in exploded builds after module system
>>>>>>>>> initialization.  The fix uses the module lock to synchronize 
>>>>>>>>> access
>>>>>>>>> to the _exploded_entries data structure (which is only used by
>>>>>>>>> exploded builds).
>>>>>>>>>
>>>>>>>>> Note that the above capability already exists for regular builds.
>>>>>>>>>
>>>>>>>>> Open Webrev:
>>>>>>>>> http://cr.openjdk.java.net/~hseigel/bug_8178604/webrev/index.html
>>>>>>>>>
>>>>>>>>> JBS Bug: https://bugs.openjdk.java.net/browse/JDK-8178604
>>>>>>>>>
>>>>>>>>> The fix was tested with JCK tests, the JTreg hotspot, java/io,
>>>>>>>>> java/lang, java/util and other tests, the RBT tier2 -tier5 tests,
>>>>>>>>> the co-located NSK tests, and with JPRT.  The JTReg and JCK tests
>>>>>>>>> were run with an exploded build.  Also, the example program in 
>>>>>>>>> the
>>>>>>>>> JBS bug was run by hand to verify the fix.
>>>>>>>>>
>>>>>>>>> Thanks, Harold
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>
>>



More information about the hotspot-runtime-dev mailing list