RFR (S): 8011803: release_C_heap_structures is never called for anonymous classes.
Coleen Phillimore
coleen.phillimore at oracle.com
Wed Apr 17 08:57:26 PDT 2013
Mikael, Thanks for looking at this in detail.
On 4/15/2013 4:23 AM, Mikael Gerdin wrote:
> Coleen,
>
> On 2013-04-12 23:36, Coleen Phillimore wrote:
>> On 4/12/2013 3:03 PM, Coleen Phillimore wrote:
>>>
>>> Hi,
>>>
>>> I have updated the webrev to split the serviceability actions and the
>>> deleting C heap data for classes in ClassLoaderData. I left the
>>> serviceability actions in dictionary::do_unloading() to avoid
>>> rewalking the ClassLoaderData _klasses. For
>>> release_C_heap_structures(), all the _klasses are walked at the end.
>>> This should work for Markus G's new serviceability changes with minor
>>> modifications.
>>
>> Reload if you looked at this already. Stefan convinced me that walking
>> the class list in the ClassLoaderData::unload() is not too expensive, so
>> the serviceability actions have been removed from
>> dictionary::do_unloading() and done in ClassLoaderData::unload()
>> unconditionally.
>
> It looks like http://cr.openjdk.java.net/~coleenp/8011803_2/ is the
> wrong webrev since it's inconsistent with your mail.
> But I have some comments about moving the calls to
> release_c_heap_structures.
I forgot to copy it over. Please reload.
>
>
> By moving the calls to {IK,CP}::release_c_heap_structures to
> ~ClassLoaderData they will be called concurrently from the CMS thread
> through its call to ClassLoaderDataGraph::purge.
>
> Previously they were called at a safepoint since
> Dictionary::do_unloading is only called at safepoint.
> A cursory inspection suggests that this is safe.
>
> However.
> This will cause the symbol refcounts to be decremented at a later
> stage than before, in fact by the time we come to ~ClassLoaderData
> we've already called SymbolTable::unkink so this will artificially
> extend the lifetime of unreferenced symbols by one full gc.
Yes, this is true and a good point. I feel like it's safer actually
since all the memory shouldn't go away before the destructor is run.
Symbols aren't reclaimed that much so this change is not likely to cause
a measurable increase in footprint between GC's (famous last words).
Coleen
>
> /Mikael
>
>>
>>>
>>> open webrev at http://cr.openjdk.java.net/~coleenp/8011803_2/
>>>
>>> thanks,
>>> Coleen
>>>
>>> On 4/12/2013 8:38 AM, Coleen Phillimore wrote:
>>>> On 4/12/2013 4:48 AM, Stefan Karlsson wrote:
>>>>> On 04/11/2013 10:52 PM, Coleen Phillimore wrote:
>>>>>> Summary: Call this function from CLD::unload() now for anonymous
>>>>>> classes.
>>>>>>
>>>>>> Anonymous classes aren't in the system dictionary so
>>>>>> release_C_heap_structures isn't called for them if they are
>>>>>> unloaded. I fixed this for jdk8 because they are in the class
>>>>>> loader data graph but for jdk7, I don't know how to fix this. They
>>>>>> are unloaded by being garbage collected after the references are
>>>>>> dropped.
>>>>>>
>>>>>> Tested with ute tests vm.mvlm.testlist nsk.monitoring.testlist and
>>>>>> jdk/test/java/lang/invoke tests.
>>>>>>
>>>>>> open webrev at http://cr.openjdk.java.net/~coleenp/8011803/
>>>>>> bug link at http://bugs.sun.com/view_bug.do?bug_id=8011803
>>>>>
>>>>> I've two comments.
>>>>>
>>>>> 1) It's unfortunate that we now call unload_class() at two different
>>>>> places in the code. It makes it harder to understand the
>>>>> deallocation of metadata. It would be better to keep the calls to
>>>>> unload_class() for ordinary InstanceKlasses and anonymous classes
>>>>> together.
>>>>
>>>> Hi Stefan, Thank you for looking at this. This is the feedback I
>>>> was looking for.
>>>>
>>>> I went back and forth about moving the regular class unloading
>>>> actions for everything in unload (or ~ClassLoaderData), but I didn't
>>>> want to introduce a _klasses walk for all the class loaders. We're
>>>> already walking them in the system dictionary purge.
>>>>
>>>> For my change I'm walking these classes if
>>>> UseCompressedKlassPointers, and Markus is walking them for
>>>> serviceability (hopefully under some flag) so maybe I should just
>>>> do it.
>>>>
>>>>>
>>>>> 2) This change actually breaks the Tracing class unloading event
>>>>> that Markus is working on. That code walk the
>>>>> ClassLoaderDataGraph::_unloading list in
>>>>> ClassLoaderDataGraph::do_unloading and use the information in the
>>>>> classes of the CLDs that are about to be unloaded. With this patch
>>>>> they probably crash because some pointers in the anonymous classes
>>>>> will be trashed.
>>>>>
>>>>
>>>> I thought about that, since I've been talking to Markus about this. I
>>>> wanted to consolidate the serviceability calls in one place and
>>>> calling InstanceKlass::unload_class() that notifies serviceability in
>>>> the ~ClassLoaderData destructor might be too late. It might not be
>>>> though. I think the walk in the destructor might be better for
>>>> release_C_heap_structures though.
>>>>
>>>>> I have a suggestion on how to solve both points above. It's probably
>>>>> easier to show with a pseudo patch:
>>>>>
>>>>> $ hg diff
>>>>> diff --git a/src/share/vm/classfile/classLoaderData.cpp
>>>>> b/src/share/vm/classfile/classLoaderData.cpp
>>>>> --- a/src/share/vm/classfile/classLoaderData.cpp
>>>>> +++ b/src/share/vm/classfile/classLoaderData.cpp
>>>>> @@ -671,7 +671,6 @@
>>>>> }
>>>>> seen_dead_loader = true;
>>>>> ClassLoaderData* dead = data;
>>>>> - dead->unload();
>>>>> data = data->next();
>>>>> // Remove from loader list.
>>>>> if (prev != NULL) {
>>>>> @@ -683,9 +682,24 @@
>>>>> dead->set_next(_unloading);
>>>>> _unloading = dead;
>>>>> }
>>>>> +
>>>>> + report_class_unloading_info(_unloading);
>>>>> +
>>>>> + ClassLoaderDataGraph::unload_classes();
>>>>> +
>>>>> return seen_dead_loader;
>>>>> }
>>>>>
>>>>> +void ClassLoaderDataGraph::unload_classes() {
>>>>> + ClassLoaderData* list = _unloading;
>>>>> + ClassLoaderData* next = list;
>>>>> + while (next != NULL) {
>>>>> + for (Klass* k = next->_klasses; k != NULL; k = k->next_link()) {
>>>>> + k->unload_class();
>>>>> + }
>>>>> + }
>>>>> +}
>>>>> +
>>>>
>>>> That's too much extra walking. But maybe we can split the
>>>> serviceability stuff into ClassLoaderData::unload() and do the
>>>> release_C_heap_structures() into the ClassLoaderData destructor. That
>>>> seems better. Maybe Markus could put his callback into
>>>> CLD::unload().
>>>>
>>>> Thanks! I will change this and resend.
>>>> Coleen
>>>>
>>>>> void ClassLoaderDataGraph::purge() {
>>>>> ClassLoaderData* list = _unloading;
>>>>> _unloading = NULL;
>>>>> diff --git a/src/share/vm/classfile/dictionary.cpp
>>>>> b/src/share/vm/classfile/dictionary.cpp
>>>>> --- a/src/share/vm/classfile/dictionary.cpp
>>>>> +++ b/src/share/vm/classfile/dictionary.cpp
>>>>> @@ -157,9 +157,6 @@
>>>>> // to be unloaded.
>>>>> // Notify the debugger and clean up the class.
>>>>> class_was_unloaded = true;
>>>>> -
>>>>> - // perform unloading actions on this class
>>>>> - ik->unload_class();
>>>>> }
>>>>> // Also remove this system dictionary entry.
>>>>> purge_entry = true;
>>>>>
>>>>> As a bonus, the dictionary()->do_unloading() will then only do a
>>>>> simple purge of the SystemDictionary.
>>>>>
>>>>> What do you think?
>>>>>
>>>>> thanks,
>>>>> StefanK
>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Coleen
>>>>>
>>>>
>>>
>>
More information about the hotspot-dev
mailing list