Request for review 8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
Coleen Phillimore
coleen.phillimore at oracle.com
Thu Nov 29 09:38:39 PST 2012
Thanks again for the code review, Stefan.
On 11/29/2012 07:12 AM, Stefan Karlsson wrote:
> 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.
>
Yes, that was a bug. I moved keep_alive setting into
ClassLoaderDataGraph::add.
>
> 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.
>
Reverted file.
>
> 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) {
You're right.
>
> 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");
Okay, I rewrote this in terms of is_alive closure rather than checking
the "claimed" bit. It's asserted to be equivalent to the claimed bit
except you might change the meaning of claimed for GC someday.
bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const {
bool alive =
is_anonymous() ?
is_alive_closure->do_object_b(_klasses->java_mirror()) :
class_loader() == NULL ||
is_alive_closure->do_object_b(class_loader());
assert(!alive || claimed(), "must be claimed");
return alive;
}
And ClassLoaderDataGraph::do_unloading() does:
while (data != NULL) {
if (data->keep_alive() || data->is_alive(is_alive_closure)) {
... continue ...
>
> 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;
> }
Fixed.
>
>
> 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);
> }
This would be nice if it's true. I don't really have a way of proving
it though and JSR 292 keeps changing so it might not stay true. I'll
add a FIXME comment to this though.
Coleen
>
> 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