RFR 8178604: JVM does not allow defining boot loader modules in exploded build after module system initialization
Lois Foltan
lois.foltan at oracle.com
Thu May 11 11:13:31 UTC 2017
This looks good.
Lois
On 5/10/2017 5:18 PM, harold seigel wrote:
>
> 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