RFR: 8319932: [JVMCI] class unloading related tests can fail on libgraal

David Holmes dholmes at openjdk.org
Thu Feb 29 06:03:52 UTC 2024


On Thu, 29 Feb 2024 05:56:39 GMT, David Holmes <dholmes at openjdk.org> wrote:

>> This PR addresses a race in `runtime/ClassInitErrors/InitExceptionUnloadTest.java` that is exposed by libgraal which sets the [default value for `TypeProfileWidth` to 8](https://github.com/openjdk/jdk/blob/eb4b6fa6212380c9b6d3c94f5aa3384f12a0c125/src/hotspot/share/compiler/compilerDefinitions.cpp#L429).
>> 
>> The problem is that `InitExceptionUnloadTest$SpecialException` is loaded by a [custom class loader](https://github.com/openjdk/jdk/blob/eb4b6fa6212380c9b6d3c94f5aa3384f12a0c125/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java#L106) and appears in the profile of `String.valueOf` as shown by `-XX:+PrintMethodData`:
>> 
>> static java.lang.String::valueOf(Ljava/lang/Object;)Ljava/lang/String;
>>   interpreter_invocation_count: 957
>>   invocation_counter: 957
>>   backedge_counter: 0
>>   decompile_count: 0
>>   mdo size: 496 bytes
>> 
>>    0 nofast_aload_0
>>    1 ifnonnull 10
>>   0 bci: 1 BranchData taken(698) displacement(56)
>>                                     not taken(0)
>>    4 fast_aldc_w "null"
>>    7 goto 14
>>   32 bci: 7 JumpData taken(0) displacement(168)
>>   10 nofast_aload_0
>>   11 invokevirtual 1023 <java/lang/Object.toString()Ljava/lang/String;>
>>   56 bci: 11 VirtualCallData count(2) entries(8)
>>                                     'java/lang/String'(470 0.67)
>>                                     'java/lang/StackTraceElement'(204 0.29)
>>                                     'java/lang/Error'(1 0.00)
>>                                     'java/lang/NoClassDefFoundError'(6 0.01)
>>                                     'java/lang/ExceptionInInitializerError'(8 0.01)
>>                                     'InitExceptionUnloadTest$SpecialException'(2 0.00)          <===== unloadable type in profile
>>                                     'java/lang/OutOfMemoryError'(2 0.00)
>> 
>> 
>> When this method is being compiled at tier 3, C1 makes a strong GC root for each type in the profile. Only once the compilation completes, are these strong roots released.
>> 
>> The test currently triggers class unloading via a [whitebox full GC](https://github.com/openjdk/jdk/blob/eb4b6fa6212380c9b6d3c94f5aa3384f12a0c125/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java#L67) and then immediately expects the classes to be unloaded. If the above C1 compilation is still in progress, the classes may not yet be unloaded.
>> 
>> This PR modifies the test to add a retry loop around the unloading trigger and the check for unloaded classes.
>
> test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java line 131:
> 
>> 129:         int attempt = 0;
>> 130:         while (!loadedClasses.isEmpty() && attempt < 20) {
>> 131:             ClassUnloadCommon.triggerUnloading();
> 
> This sort of re-try logic is what is supposed to be encapsulated by `ClassUnloadCommon.triggerUnloading`, or perhaps more accurately the underlying `WhiteBox.fullGC()`. Individual tests should not have to know about such things.

Is there a way to do something like `WhiteBox.waitForCompilationToComplete()` prior to calling `fullGC()`?

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/18044#discussion_r1507054180


More information about the hotspot-runtime-dev mailing list