RFR JDK-8232222: Set state to 'linked' when an archived class is restored at runtime

David Holmes david.holmes at oracle.com
Wed Jun 3 22:42:00 UTC 2020

Correction ...

On 3/06/2020 5:19 pm, David Holmes wrote:
> On 3/06/2020 3:44 pm, Ioi Lam wrote:
>> On 6/2/20 10:16 PM, David Holmes wrote:
>>> Hi Ioi,
>>> On 3/06/2020 2:55 pm, Ioi Lam wrote:
>>>> On 5/27/20 11:13 PM, David Holmes wrote:
>>>>> Hi Jiangli,
>>>>> On 28/05/2020 11:35 am, Ioi Lam wrote:
>>>>>>> I was going to take the suggestion, but realized that it would add
>>>>>>> unnecessary complications for archived boot classes with class
>>>>>>> pre-initialization support. Some agents may set
>>>>>>> JvmtiExport::should_post_class_prepare(). It's worthwhile to support
>>>>>>> class pre-init uniformly for archived boot classes with
>>>>>>> JvmtiExport::should_post_class_prepare() enabled or disabled.
>>>>>> This would introduce behavioral changes when JVMTI is enabled:
>>>>>> + The order of JvmtiExport::post_class_prepare is different than 
>>>>>> before
>>>>>> + JvmtiExport::post_class_prepare may be called for a class that 
>>>>>> was not called before (if the class is never linked during run time)
>>>>>> + JvmtiExport::post_class_prepare was called inside the init_lock, 
>>>>>> now it's called outside of the init_lock
>>>>> I have to say I share Ioi's concerns here. This change will impact 
>>>>> JVM TI agents in a way we can't be sure of. From a specification 
>>>>> perspective I think we are fine as linking can be lazy or eager, so 
>>>>> there's no implied order either. But this would be a behavioural 
>>>>> change that will be observable by agents. (I'm less concerned about 
>>>>> the init_lock situation as it seems potentially buggy to me to call 
>>>>> out to an agent with the init_lock held in the first place! I find 
>>>>> it hard to imagine an agent only working correctly if the init_lock 
>>>>> is held.)
>>>> David,
>>>> The init_lock has a serializing effect. The callback for a subclass 
>>>> will not be executed until the callback for its super class has been 
>>>> finished.
>>> Sorry I don't see that is the case. The init_lock for the subclass is 
>>> distinct from the init_lock of the superclass, and linking of 
>>> subclasses and superclasses is independent.
>> In InstanceKlass::link_class_impl, you first link all of your super 
>> classes.
>> If another thread is already linking your super class, you will block 
>> on that superclass's init_lock.
> The point is that there is already a race in terms of the execution of 
> the two callbacks. So while this change can certainly produce a 
> different result to what would previously be seen, such a result is 
> already possible in the general case.
>> Of course, I may be wrong and my analysis may be bogus. But I hope you 
>> can appreciate that this is not going to be a trivial change to analyze.
> Yes I agree. While in general ordering of the class_prepare callbacks is 
> not guaranteed for independent classes, if a given application 
> explicitly loads and links classes in a known order then it can 
> (reasonably) expect its callbacks to execute in that order. If this 
> change means classes will now be linked in an order independent of what 
> the normal runtime order would be then that could be a problem for 
> existing agents.
> So where does this leave us? The change is within spec, but could 
> trigger changes in agent behaviour that we can't really evaluate 
> a-priori. So as you say we should have a fairly good reason for doing 
> this. I can easily envisage that pre-linking when no callbacks are 
> enabled would be a performance boost. But with callbacks enabled and 
> consuming CPU cycles any benefit from pre-linking could be lost in the 
> noise.
> What if we did as Ioi suggested and only set the class as linked in 
> restore_unshareable_info if !JvmtiExport::should_post_class_prepare(); 
> and in addition in InstanceKlass::link_class_imp we added an additional 
> check at the start:
> // Pre-linking at load time may have been disabled for shared classes,
> // but we may be able to do it now.
> if (JvmtiExport::should_post_class_prepare() &&
>      !BytecodeVerificationLocal &&
>      loader_data->is_the_null_class_loader_data()) {
>    _init_state = linked;
> }

There should obviously be a check for is_shared() in there as well.


> ?
> That avoids the problem of changing the JVM TI callback behaviour, but 
> also shortens the link time path when the callbacks are enabled.
> Hope I got that right. :)
> David
> -----
>> Thanks
>> - Ioi
>>> David
>>> -----
>>>> With the proposed patch, the callback for both the super class and 
>>>> subclass can proceed in parallel. So if an agent performs class 
>>>> hierarchy analysis, for example, it may need to perform extra 
>>>> synchronization.
>>>> This is just one example that I can think of. I am sure there are 
>>>> other issues that we have not thought about.
>>>> The fact is we are dealing with arbitrary code in the callbacks, and 
>>>> we are changing the conditions of how they are called. The calls 
>>>> happen inside very delicate code (class loading, system dictionary). 
>>>> I am reluctant to do the due diligence, which is substantial, of 
>>>> verifying that this is a safe change, unless we have a really 
>>>> compelling reason to do so.
>>>> Thanks
>>>> - Ioi

More information about the hotspot-runtime-dev mailing list