RFR (S) JDK-8007725 - Klass::restore_unshareable_info() triggers assert(k->java_mirror() == NULL)
Karen Kinnear
karen.kinnear at oracle.com
Thu Mar 14 08:24:02 PDT 2013
Ioi,
Thank you for fixing this. And thank you so much for asking me to review this - this logic is very tricky.
I had a couple of questions/comments please:
1) klass.cpp line 490, systemDictionary.cpp line 808
I believe that there are other possible PENDING_EXCEPTIONS in addition to OOM we can get here -
could you possibly modify the comments to say something like "An exception, such as OOM, ..."
(e.g. I believe we could get here due to a loader constraint exception)
2) method.cpp 804, klass.cpp 489
Can you possibly explain why you would not see a problem in DumpSharedSpaces?
For remove_unshareable_info I am confused when you would clean up a number of the fields
but leave the class_loader_data?
3. klass.cpp remove_unshareable_info
I'm still trying to figure out exactly how you determined the fields to be cleared.
I get the set that matches restore_unshareable_info.
If the other fields got filled in, then another thread got its hands on this instanceKlass, via
a sibling or subklass - and you don't want to be cleaning this up at all, so I'm wondering
if that would be an assertion instead?
4. Could you possibly remove lines 1162-1166 - I don't think those are pertinent
post-nopermgen.
5. systemDictionary.cpp
I'm wondering if you want to move the cleanup request to a different place.
If the load was successful, but the check_constraints on the initiating loader fails - I think you want to
leave the klass loaded by the defining loader (null) and leave the information intact.
(We allow a defineclass to succeed and future lookups to find the class/defining loader even if
the initiating loader fails due to loader constraints or later checkpackageaccess for instance)
I don't quite understand where the exception is happening that you are cleaning up for.
Where did you see an OOM? Where else could they happen here? What other
exceptions could happen? I think this has to be handled at a tighter level of granularity so
we know exactly when this clean up is needed.
So I'm assuming you are doing a cleanup of the unshareable info because:
find_shared_class succeeded, resolve_super_or_fail on superclasses/interfaces succeeded and
restore_unshareable_info succeeded.
Can we assume load_shared_class succeeded or do we need a check there in case notify_class_loaded
failed?
For the bootloader today, LOAD_INSTANCE is not done in parallel, so we are not going to run
into the situation in which another thread is loading the same class in the LOAD_INSTANCE sense.
That said, once we add the instanceKlass to the systemdictionary - any other thread could
find it and use it - so we don't want to clean it up - it may be in use.
In load_instance_class if load_shared_class succeeds, you call find_or_define_instance_class, which
calls define_class.
Inside find_or_define_instance_class and define_instance_class you can have failures
before you add to the systemdictionary - in which case you want to do this cleanup. If the failures are
after that point - this thread may not get the information back due to a pending exception, but other
threads may use the information - so you don't want to do the cleanup. So the key is - if update_dictionary
succeeded - don't do the cleanup. If it did not, you want the cleanup.
Coleen is planning to put in code to cleanup the instanceKlass - and this should go the same place I
would assume, so you probably want to discuss this closely with her.
thanks,
Karen
On Mar 14, 2013, at 1:49 AM, Ioi Lam wrote:
> Hi, could someone review this? This fixes a crash related to OOM handling.
>
> Thanks
> - Ioi
>
> On 03/11/2013 12:47 PM, Ioi Lam wrote:
>> Please review:
>> http://cr.openjdk.java.net/~iklam/8007725/null_mirror_001/
>>
>> Bug: NPG: Klass::restore_unshareable_info() triggers
>> assert(k->java_mirror() == NULL)
>>
>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8007725
>> or https://jbs.oracle.com/bugs/browse/JDK-8007725
>>
>> (The bugs.sun.com page may be unavailable for a couple of days due
>> to recent change of confidentiality status.)
>>
>> Summary of fix:
>>
>> The assert is at:
>>
>> --------
>> # Internal Error (src/share/vm/classfile/javaClasses.cpp:527)
>> # assert(k->java_mirror() == NULL) failed: should only assign mirror once
>> java_lang_Class::create_mirror(KlassHandle)
>> Klass::restore_unshareable_info()
>> InstanceKlass::restore_unshareable_info()
>> instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle,Handle)
>> --------
>>
>> This happens if during class loading, an OOM happened after
>> Klass::restore_unshareable_info() has called
>> java_lang_Class::create_mirror(), but before the class loading is completed.
>>
>> At this point, the class is not in the system dictionary. However the
>> Klass structure is partially initialized.
>>
>> If the app tries to load the same class again, the assert happens.
>>
>> The fix is to undo all work performed by
>> InstanceKlass::restore_unshareable_info().
>>
>> Tests executed:
>>
>> * JPRT
>> * JCK (vm, lang, api/signaturetest)
>> * UTE (vm.quick.testlist, )
>>
>> Thanks,
>> Ioi
>
More information about the hotspot-runtime-dev
mailing list