RFR(S): 8232081: Try to link all classes during dynamic CDS dump
Calvin Cheung
calvin.cheung at oracle.com
Thu Mar 5 05:13:02 UTC 2020
Hi David, Ioi,
Here's an updated webrev which doesn't involve changing
InstanceKlass::verify_on() and made use of the changes for JDK-8240481.
http://cr.openjdk.java.net/~ccheung/jdk15/8232081/webrev.03/
thanks,
Calvin
On 3/1/20 10:14 PM, David Holmes wrote:
> Hi Calvin,
>
> On 28/02/2020 4:12 pm, Calvin Cheung wrote:
>> Hi David,
>>
>> On 2/27/20 5:40 PM, David Holmes wrote:
>>> Hi Calvin, Ioi,
>>>
>>> Looking good - comments below.
>>>
>>> A meta-question: normal application classes are rarely loaded but
>>> not linked so I'm a little surprised this is an issue. What is the
>>> main source of such classes - generated classes like lambda forms?
>>> Also why do we need to link them when loading from the archive if
>>> they were never linked when the application actually executed ??
>>
>> I saw that Ioi already answered the above.
>>
>> I'll try to answer your questions inline below..
>
> Responses inline below ...
>
>>>
>>> On 28/02/2020 10:48 am, Calvin Cheung wrote:
>>>> Hi David, Ioi,
>>>>
>>>> Thanks for your review and suggestions.
>>>>
>>>> On 2/26/20 9:46 PM, Ioi Lam wrote:
>>>>>
>>>>>
>>>>> On 2/26/20 7:50 PM, David Holmes wrote:
>>>>>> Hi Calvin,
>>>>>>
>>>>>> Adding core-libs-dev as you are messing with their code :)
>>>>>>
>>>>>> On 27/02/2020 1:19 pm, Calvin Cheung wrote:
>>>>>>> JBS: https://bugs.openjdk.java.net/browse/JDK-8232081
>>>>>>> webrev:
>>>>>>> http://cr.openjdk.java.net/~ccheung/jdk15/8232081/webrev.00/
>>>>>>>
>>>>>>> The proposed changeset for this RFE adds a
>>>>>>> JVM_LinkClassesForCDS() function to be called from
>>>>>>> java/lang/Shutdown to notify the JVM to link the classes loaded
>>>>>>> by the builtin class loaders. The
>>>>>>
>>>>>> This would be much less disruptive if this was handled purely on
>>>>>> the VM side once we have started shutdown. No need to make any
>>>>>> changes to the Java side then, nor jvm.cpp.
>>>>>>
>>>>>
>>>>> Hi David,
>>>>>
>>>>> To link the classes, we need to be able to run Java code -- when
>>>>> linking a class X loaded by the app loader, X will be verified.
>>>>> During verification of X, we may need to load additional classes
>>>>> from the app loader, which executes Java code during its class
>>>>> loading operations.
>>>>>
>>>>> We also need to handle all the exit conditions. As far as I can
>>>>> tell, an app can exit the JVM in two ways:
>>>>>
>>>>> (1) Explicitly calling System.exit(). This will call
>>>>> java.lang.Shutdown.exit() which does this:
>>>>>
>>>>> http://hg.openjdk.java.net/jdk/jdk/file/0edc7fd0d7a3/src/java.base/share/classes/java/lang/Shutdown.java#l163
>>>>>
>>>>>
>>>>> beforeHalt(); // native
>>>>> runHooks();
>>>>> halt(status);
>>>>>
>>>>> (2) When all non-daemon threads have died (e.g., falling out of
>>>>> the bottom of HelloWorld.main()). There's no explicit call to
>>>>> System.exit(), but the JVM will proactively call
>>>>> java.lang.Shutdown.shutdown() inside
>>>>> JavaThread::invoke_shutdown_hooks()
>>>>>
>>>>> http://hg.openjdk.java.net/jdk/jdk/file/0edc7fd0d7a3/src/hotspot/share/runtime/thread.cpp#l4331
>>>>>
>>>>> http://hg.openjdk.java.net/jdk/jdk/file/0edc7fd0d7a3/src/java.base/share/classes/java/lang/Shutdown.java#l184
>>>>>
>>>>>
>>>>> If we want to avoid modifying the Java code, I think we can
>>>>> intercept JVM_BeforeHalt() and
>>>>> JavaThread::invoke_shutdown_hooks(). This way we should be able to
>>>>> handle all the classes (except those that are loaded inside
>>>>> Shutdown.runHooks).
>>>>
>>>> I've implemented the above. No changes to the Java side.
>>>>
>>>> updated webrev:
>>>>
>>>> http://cr.openjdk.java.net/~ccheung/jdk15/8232081/webrev.01/
>>>
>>> This looks much better to me. I wasn't sure if you were that
>>> concerned about catching the classes loaded by the Shutdown hooks,
>>> but it is good you are not as it seems problematic to me to trigger
>>> class loading etc after the shutdown hooks have executed - you may
>>> hit unexpected conditions. So this approach is good.
>>>
>>> A few minor comments:
>>>
>>> src/hotspot/share/memory/metaspaceShared.cpp
>>> src/hotspot/share/memory/metaspaceShared.hpp
>>>
>>> Why the change from TRAPS to "Thread* THREAD"?
>> I forgot why I changed it but I've changed it back and it still works.
>
> Ok.
>
>>>
>>> ---
>>>
>>> src/hotspot/share/oops/instanceKlass.cpp
>>>
>>> I'm not clear how verify_on is used so am unsure how the additional
>>> error state check may affect code unrelated to dynamic dumping ??
>>
>> Some of the appcds tests by design have some classes which fail
>> verification. Without the change, the following assert would fail:
>>
>> void vtableEntry::verify(klassVtable* vt, outputStream* st) {
>> Klass* vtklass = vt->klass();
>> if (vtklass->is_instance_klass() &&
>> (InstanceKlass::cast(vtklass)->major_version() >=
>> klassVtable::VTABLE_TRANSITIVE_OVERRIDE_VERSION)) {
>> *assert*(method() != NULL, "must have set method");
>> }
>
> Okay so you need to exclude for that case but ...
>
>> Here's the call stack during dynamic CDS dump to the above function:
>>
>> vtableEntry::verify(klassVtable *, outputStream *) : void
>> klassVtable::verify(outputStream *, bool) : void
>> InstanceKlass::verify_on(outputStream *) : void
>> Klass::verify() : void
>> ClassLoaderData::verify() : void
>> ClassLoaderDataGraph::verify() : void
>> Universe::verify(enum VerifyOption, const
>> char *) : void
>> Universe::verify(const char *) : void
>> DynamicArchiveBuilder::verify_universe(const char *) : void
>> DynamicArchiveBuilder::doit() : void (2 matches)
>> VM_PopulateDynamicDumpSharedSpace::doit() : void
>> VM_Operation::evaluate() : void
>>
>> The is_linked() function is implemented as:
>>
>> bool is_linked() const { return _init_state >=
>> linked; }
>>
>> which includes 'initialization_error'.
>
> ... AFAICS Universe::verify is call from a number of places, all of
> which would reach this modified code. As that existing code has
> included classes that are in the error state then it seems to me that
> unless you can prove otherwise you need to keep the existing code
> as-is for the non-CDS dump case.
>
>> A previous version of the changeset (including the change in question
>> in instanceKlass.cpp) passed tier1 - 4 testing. Let me know if I
>> should run other tests to make sure the change is good.
>
> There may well not be a test that covers this.
>
> Thanks,
> David
>
>>>
>>> Also can I suggest (as you are touching this code) to delete the
>>> ancient comment:
>>>
>>> 3580 // $$$ This used to be done only for m/s collections. Doing it
>>> 3581 // always seemed a valid generalization. (DLD -- 6/00)
>>
>> I'm glad that you suggested to remove the above comment. I've no clue
>> what it means either.
>>
>> updated webrev:
>>
>> http://cr.openjdk.java.net/~ccheung/jdk15/8232081/webrev.02/
>>
>> thanks,
>> Calvin
>>>
>>> Thanks,
>>> David
>>> -----
>>>
>>>> I also updated the test to test the shutdown hook and System.exit()
>>>> scenarios.
>>>>
>>>> All appcds tests passed on my linux host. I'll run more tests using
>>>> mach5.
>>>>
>>>> thanks,
>>>>
>>>> Calvin
>>>>
>>>>
>>>>>
>>>>> What do you think?
>>>>>
>>>>> - Ioi
>>>>>
>>>>>> Thanks,
>>>>>> David
>>>>>>
>>>>>>> MetaspaceShared::link_and_cleanup_shared_classes() has been
>>>>>>> modified to handle both static and dynamic CDS dump. For dynamic
>>>>>>> CDS dump, only classes loaded by the builtin class loaders will
>>>>>>> be linked. Local performance testing using javac on
>>>>>>> HelloWorld.java shows an improvement of >5%.
>>>>>>>
>>>>>>> Passed tier1 - 4 tests.
>>>>>>>
>>>>>>> thanks,
>>>>>>>
>>>>>>> Calvin
>>>>>>>
>>>>>
More information about the core-libs-dev
mailing list