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

harold seigel harold.seigel at oracle.com
Wed May 10 21:18:22 UTC 2017


Hi Lois, David,

Please review this latest webrev that initializes _exploded_entries 
without locking:

    http://cr.openjdk.java.net/~hseigel/bug_8178604.4/webrev/index.html

Thanks, Harold


On 5/10/2017 1:19 PM, Lois Foltan wrote:
> On 5/9/2017 5:18 PM, David Holmes wrote:
>> On 9/05/2017 11:14 PM, harold seigel wrote:
>>> 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
>>
>> Then as I said, why do we need any locking? I note Lois is the one 
>> that requested this and you questioned it. I also question it.
>
> Thank you Harold for investigating this.  I stand corrected, it seems 
> that we do not need the lock after all when allocating 
> ClassLoader::_exploded_entries.
> Lois
>
>>
>> Thanks,
>> David
>> -----
>>
>>> 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