Request for review 8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
Stefan Karlsson
stefan.karlsson at oracle.com
Thu Nov 29 04:12:55 PST 2012
Hi Coleen,
I took a closer look at the ClassLoaderData::anonymous_class_loader_data:
I'm wondering if we have a potential bug in that code. Here's a some
pseudo code for that:
cld = new ClassLoaderData(loader)
put_on_cld_list(cld) // GC can now find it
init_dependencies // GC can occur at this line
cld->set_keep_alive(true) // We mark that this CLD should be
considered live by the GC
I think the set_keep_alive call should be done before init_dependencies
are set up. Otherwise this CLD might be prematurely unloaded.
Some minor comments:
http://cr.openjdk.java.net/~coleenp/8000662_3/src/os_cpu/linux_x86/vm/os_linux_x86.cpp.patch
Unrelated whitespace change.
http://cr.openjdk.java.net/~coleenp/8000662_3/src/share/vm/classfile/classLoaderData.cpp.udiff.html
is_alive isn't used anymore:
+ void ClassLoaderData::unload(BoolObjectClosure* is_alive) {
I think we are using the wrong abstraction when we are looking at the
claimed bits here. I'll revisit this code after this has been pushed.
- if (data->class_loader() == NULL ||
is_alive->do_object_b(data->class_loader())) {
- assert(data->claimed(), "class loader data must have been claimed");
+ if (data->claimed() || data->keep_alive()) {
+ assert(data->class_loader() == NULL ||
is_alive->do_object_b(data->class_loader()), "class loader data must be
live");
http://cr.openjdk.java.net/~coleenp/8000662_3/src/share/vm/classfile/classLoaderData.hpp.patch
Unnecessary change:
bool is_unloading() const {
- assert(!(is_the_null_class_loader_data() && _unloading), "The null
class loader can never be unloaded");
+ assert(!(this == the_null_class_loader_data() && _unloading), "The
null class loader can never be unloaded");
return _unloading;
}
http://cr.openjdk.java.net/~coleenp/8000662_3/src/share/vm/classfile/systemDictionary.cpp.patch
I don't know if this is needed or not. I thought we would have
registered some sort of object in the resolved_references to keep the
mirror alive. But I guess that's not the case.
(*appendix_result) = Handle(THREAD, appendix);
+ // the target is stored in the cpCache and if a reference to this
+ // MethodName is dropped we need a way to make sure the
+ // class_loader containing this method is kept alive.
+ ClassLoaderData* this_key =
InstanceKlass::cast(accessing_klass())->class_loader_data();
+ this_key->record_dependency(m->method_holder(), CHECK_NULL); //
Can throw OOM
return methodHandle(THREAD, m);
}
StefanK
On 11/29/2012 01:43 AM, Coleen Phillimore wrote:
>
> Please review updated changes to fix the nashorn OOMs from using jsr
> 292 anonymous classes. The changes to fix bug 8003720 NPG: Method in
> interpreter stack frame can be deallocated
> <https://jbs.oracle.com/bugs/browse/JDK-8003720> have been removed
> from this changeset in favor of the change that Stefan checked in on
> Monday. Note - there is no target-specific code in this change now.
>
> Other changes since last webrev are several cleanups from internal
> discussions.
>
> open webrev at http://cr.openjdk.java.net/~coleenp/8000662_3/
> bug link at http://bugs.sun.com/view_bug.do?bug_id=8000662_3
>
> Retesting with NSK vm tests. I'll try to describe things better
> below in reply to David's questions.
>
> On 11/11/2012 11:32 PM, David Holmes wrote:
>> Hi Coleen,
>>
>> :)
>>
>> Can you explain the old and new relationships between these various
>> objects please. As I understand it JSR-292 introduced this special
>> kind of class - the anonymous class - and they differ from regular
>> classes in important ways (mainly that they can be collected before
>> their classloader), and pre-NPG this all "just worked". The NPG
>> changes added the ClassLoaderData metadata objects and changed some
>> of the associations that anonymous classes actually relied upon and
>> as a result they stopped getting GC'd in some cases, and were
>> prematurely GC'd in others (I hope I got that right). This changeset
>> addresses these problems.
>
> This is correct. I don't think I could have written this better. Yes,
> in the old Permgen world, when the MethodHandles that contained the
> mirror to the anonymous class was unreferenced, the klass and all the
> metadata associated with it would be collected. Now with
> ClassLoaderData objects, collection of metadata is tied to these
> objects. The initial naive implementation just added the anonymous
> classes to the host_klass's ClassLoaderData object, which before b63
> (I think) was the boot class loader. So the anonymous classes were
> never collected.
>
> This changeset gives each anonymous class it's own ClassLoaderData
> object and uses it's java_mirror to determine whether the anonymous
> class is still live and whether the ClassLoaderData object can be
> unloaded.
>
> We have been doing some tuning to determine how large the metaspace
> should be for these special cases. That is ongoing.
>
>>
>> I've been trying to follow this from the beginning and still don't
>> have a clear understanding on what the relationships between
>> ClassLoader, Class, "anonymous class" and ClassLoaderData objects
>> are. So a clear picture of what relationships exist (particularly
>> this new 1:N association) would be appreciated, and help make the
>> code changes more understandable to me.
>
> I can't draw pictures without a whiteboard! But you may have several
> CLD objects that correspond to one class_loader oop. Each CLD object
> points to the class_loader, but the class_loader only points to the
> primary CLD object. The additional CLD objects are for anonymous
> classes, which are kept live by their mirrors, not the class_loader.
> That's the source of many of the changes in this changeset.
>
> Thanks,
> Coleen
>
>>
>> Thanks,
>> David
>>
>> On 12/11/2012 1:51 PM, Coleen Phillimore wrote:
>>>
>>> This change creates a ClassLoaderData object for each JSR 292 anonymous
>>> class, so that the metadata and mirror object for the anonymous class
>>> can be reclaimed when the anonymous class is no longer referenced. The
>>> java_lang_ClassLoader object for the anonymous class is the same as its
>>> host_class. Most of this change is to break the assumption that there's
>>> a 1-1 relationship between java_lang_ClassLoader Java objects and
>>> ClassLoaderData metadata objects in the VM. Also, nmethods and other
>>> things that were strong roots for java_lang_ClassLoader objects have to
>>> also be strong roots for java_lang_Class objects for anonymous classes.
>>>
>>> There were also changes to move the dependencies out of the
>>> java_lang_ClassLoader object to the ClassLoaderData type. This type is
>>> preallocated so that CMS will have card marks to track additions to the
>>> dependencies. Please check this, Stefan!
>>>
>>> Also, in this change is the addition of mirrors to the interpreter
>>> frame
>>> and a test case that shows why this is necessary. An interpreter frame
>>> can be running while it's class loader is unloaded in some special
>>> circumstances. It is easier to do this with JSR292 static MethodHandle
>>> code. Some people are looking for a platform independent way to do
>>> this,
>>> by changing code in GC. While this target-dependent interpreter code is
>>> unfortunate, the concept is simple. If the latter effort succeeds, we
>>> can remove the mirror from the interpreter frame later. A note to
>>> openjdk developers - I added this mirror to zero but not to shark. More
>>> testing is necessary.
>>>
>>> Please review the following change:
>>>
>>> Summary: Add ClassLoaderData object for each anonymous class with
>>> metaspaces to allocate in. Add mirror interpreter frame.
>>>
>>> http://cr.openjdk.java.net/~coleenp/8000662/
>>> http://bugs.sun.com/view_bug.do?bug_id=8000662
>>>
>>> Tested with Nashorn tests, NSK full testlist, dacapo with CMS and G1.
>>>
>>> Thanks,
>>> Coleen
>
More information about the hotspot-dev
mailing list