RFR(S) 8231125 Improve testing of parallel loading of shared classes by the boot class loader
Ioi Lam
ioi.lam at oracle.com
Wed Sep 18 19:11:21 UTC 2019
Hi Calvin,
Thanks for the review. You're right. I changed the code to
log("thread[%d] t = %s, c = %s, l = %s", thread_id, this, clazz,
clazz.getClassLoader());
Now the output looks like this, which is what I want:
ParallelLoadThread: thread[3] t = Thread[Thread-3,5,main], c = class
ParallelClass0, l = null
ParallelLoadThread: thread[2] t = Thread[Thread-2,5,main], c = class
ParallelClass0, l = null
ParallelLoadThread: thread[1] t = Thread[Thread-1,5,main], c = class
ParallelClass0, l = null
ParallelLoadThread: thread[0] t = Thread[Thread-0,5,main], c = class
ParallelClass0, l = null
ParallelLoadThread: thread[0] t = Thread[Thread-0,5,main], c = class
ParallelClass1, l = null
ParallelLoadThread: thread[3] t = Thread[Thread-3,5,main], c = class
ParallelClass1, l = null
ParallelLoadThread: thread[1] t = Thread[Thread-1,5,main], c = class
ParallelClass1, l = null
ParallelLoadThread: thread[2] t = Thread[Thread-2,5,main], c = class
ParallelClass1, l = null
ParallelLoadThread: thread[0] t = Thread[Thread-0,5,main], c = class
ParallelClass2, l = null
ParallelLoadThread: thread[1] t = Thread[Thread-1,5,main], c = class
ParallelClass2, l = null
ParallelLoadThread: thread[3] t = Thread[Thread-3,5,main], c = class
ParallelClass2, l = null
ParallelLoadThread: thread[2] t = Thread[Thread-2,5,main], c = class
ParallelClass2, l = null
Thanks
- Ioi
On 9/18/19 11:42 AM, Calvin Cheung wrote:
> Hi Ioi,
>
> Just one comment on the v02 webrev:
>
> http://cr.openjdk.java.net/~iklam/jdk14/8231125-shared-boot-class-parallel-test.v02/test/hotspot/jtreg/runtime/cds/appcds/test-classes/ParallelLoad.java.sdiff.html
>
>
> 191 log("thread[%d] t = %s, c = %s, l = %s", i, this,
> clazz, clazz.getClassLoader());
>
> I thought i is the index into the ParallelLoad.MAX_CLASSES.
>
> Should the above i be thread_id?
>
> thanks,
>
> Calvin
>
> On 9/17/19 11:23 PM, Ioi Lam wrote:
>>
>>
>> On 9/17/19 6:27 PM, David Holmes wrote:
>>> Hi Ioi,
>>>
>>> On 18/09/2019 7:24 am, coleen.phillimore at oracle.com wrote:
>>>> http://cr.openjdk.java.net/~iklam/jdk14/8231125-shared-boot-class-parallel-test.v01/src/hotspot/share/classfile/systemDictionary.cpp.udiff.html
>>>>
>>>>
>>>> Can you add a line something like.
>>>>
>>>> + if (class_loader() == NULL) {
>>>> + // See case 3 in SystemDictionary::resolve_instance_class_or_null
>>>> + // multiple threads wait on the SystemDictionary_lock if the
>>>> boot loader class is in the placeholder table, so only
>>>> + // one thread loads the class.
>>>> + assert(ik->class_loader_data() == NULL, "boot loader classes are
>>>> not loaded in parallel");
>>>> + }
>>>> +
>>>
>>> Even with Coleen's suggested comment I still don't see what this
>>> code has to do with loading in parallel? AFAICS all you are
>>> asserting is that if the class is to be loaded by the boot-loader
>>> then the class should have been dumped by the boot-loader - no?
>>>
>> Hi David,
>>
>> When we were analyzing a recent random crash that might be caused by
>> race condition during class loading, we looked at this call to
>> restore_unshareable_info() in SystemDictionary::load_shared_class()
>>
>> ClassLoaderData* loader_data =
>> ClassLoaderData::class_loader_data(class_loader());
>> {
>> HandleMark hm(THREAD);
>> Handle lockObject = compute_loader_lock_object(class_loader,
>> THREAD);
>> check_loader_lock_contention(lockObject, THREAD);
>> ObjectLocker ol(lockObject, THREAD, true);
>> // prohibited package check assumes all classes loaded from
>> archive call
>> // restore_unshareable_info which calls ik->set_package()
>> ik->restore_unshareable_info(loader_data, protection_domain,
>> CHECK_NULL);
>> }
>>
>> Because all the crash seemed to be with shared classes loaded by the
>> boot loader, we suspect that two threads competing to load the same
>> class may arrive here simultaneously, and we will end up calling
>> ik->restore_unshareable_info() twice, with harmful side effects.
>>
>> Upon further investigation, we found that this is not the case. But
>> it will be good to have an assert to check for this -- that we won't
>> call ik->restore_unshareable_info() more than once.
>>
>> I realized that I put the assert at the wrong place, and asserted on
>> the wrong field (non-boot classes will enter load_shared_class() with
>> ik->class_loader_data() != NULL). So I changed the assert to be on
>> the java_mirror. That way, the assert works for shared classes for
>> all loaders.
>>
>> assert(!ik->is_java_mirror_restored(), "don't load the same
>> shared class twice");
>> ik->restore_unshareable_info(loader_data, protection_domain,
>> CHECK_NULL);
>> assert(ik->is_java_mirror_restored() ||
>> !SystemDictionary::Class_klass_loaded(), "must be");
>>
>> Here's an updated webrev, which also contains fixes you suggested below.
>>
>> Thanks
>> - Ioi
>>
>>> The test seems okay - the proof is in the running :)
>>>
>>> One style nit:
>>>
>>> ! for (int i=0; i<APP_LOOPS; i++) {
>>>
>>> spaces around binary operators please. This seems to impact all for
>>> loops.
>>>
>>> Also:
>>>
>>> 175 { // Avoid logging in this block so the threads
>>> can proceeds without
>>>
>>> s/proceeds/proceed/
>>>
>>> Thanks,
>>> David
>>> -----
>>>
>>>> I wonder if the ObjectLocker is really needed for non-bootclass
>>>> loaders below this code, since it appears to not be needed for boot
>>>> class loaders.
>>>>
>>>> The test changes look good. I think you're supposed to have @bug
>>>> tags in them.
>>>>
>>>> Thanks for going through this code looking for races!
>>>> Coleen
>>>>
>>>>
>>>> On 9/17/19 1:10 PM, Ioi Lam wrote:
>>>>> https://bugs.openjdk.java.net/browse/JDK-8231125
>>>>> http://cr.openjdk.java.net/~iklam/jdk14/8231125-shared-boot-class-parallel-test.v01/
>>>>>
>>>>>
>>>>>
>>>>> [1] Modified ParallelLoadTest.java to also test the loading of
>>>>> shared classes
>>>>> into the boot loader.
>>>>> [2] Modified ParallelLoad.java to minimize the initial time lag
>>>>> when the 4 parallel
>>>>> threads compete to load the same class.
>>>>> [3] Added an assert in the JVM to verify that for a shared classes
>>>>> loaded
>>>>> the boot class loader, SystemDictionary::load_shared_class is
>>>>> not called
>>>>> multiple times.
>>>>>
>>>>
>>
More information about the hotspot-runtime-dev
mailing list