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