changeset 3869:90273fc0a981

8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap Summary: Add ClassLoaderData object for each anonymous class with metaspaces to allocate in. Reviewed-by: twisti, jrose, stefank
author coleenp
date Thu, 29 Nov 2012 16:50:29 -0500
parents 2fc0334f613a
children dad48145e775
files src/share/vm/asm/codeBuffer.cpp src/share/vm/ci/ciReplay.cpp src/share/vm/ci/ciReplay.hpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classFileParser.hpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/classLoaderData.hpp src/share/vm/classfile/classLoaderData.inline.hpp src/share/vm/classfile/dictionary.cpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/javaClasses.hpp src/share/vm/classfile/loaderConstraints.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/compiler/compileBroker.cpp src/share/vm/compiler/compileBroker.hpp src/share/vm/memory/metachunk.hpp src/share/vm/memory/metaspace.cpp src/share/vm/memory/metaspace.hpp src/share/vm/memory/universe.cpp src/share/vm/oops/constantPool.cpp src/share/vm/oops/klass.cpp src/share/vm/oops/klass.hpp src/share/vm/oops/objArrayKlass.cpp src/share/vm/prims/unsafe.cpp
diffstat 26 files changed, 366 insertions(+), 250 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/asm/codeBuffer.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/asm/codeBuffer.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -492,6 +492,26 @@
   dest->verify_section_allocation();
 }
 
+// Anonymous classes need mirror to keep the metadata alive but
+// for regular classes, the class_loader is sufficient.
+static void append_oop_references(GrowableArray<oop>* oops, Klass* k) {
+  if (k->oop_is_instance()) {
+    InstanceKlass* ik = InstanceKlass::cast(k);
+    if (ik->is_anonymous()) {
+      oop o = ik->java_mirror();
+      assert (o != NULL, "should have a mirror");
+      if (!oops->contains(o)) {
+        oops->append(o);
+      }
+      return;  // only need the mirror
+    }
+  }
+  oop cl = k->class_loader();
+  if (cl != NULL && !oops->contains(cl)) {
+    oops->append(cl);
+  }
+}
+
 void CodeBuffer::finalize_oop_references(methodHandle mh) {
   No_Safepoint_Verifier nsv;
 
@@ -509,7 +529,6 @@
         if (md->metadata_is_immediate()) {
           Metadata* m = md->metadata_value();
           if (oop_recorder()->is_real(m)) {
-            oop o = NULL;
             if (m->is_methodData()) {
               m = ((MethodData*)m)->method();
             }
@@ -517,16 +536,13 @@
               m = ((Method*)m)->method_holder();
             }
             if (m->is_klass()) {
-              o = ((Klass*)m)->class_loader();
+              append_oop_references(&oops, (Klass*)m);
             } else {
               // XXX This will currently occur for MDO which don't
               // have a backpointer.  This has to be fixed later.
               m->print();
               ShouldNotReachHere();
             }
-            if (o != NULL && oops.find(o) == -1) {
-              oops.append(o);
-            }
           }
         }
       }
@@ -537,7 +553,6 @@
     for (int i = 0; i < oop_recorder()->metadata_count(); i++) {
       Metadata* m = oop_recorder()->metadata_at(i);
       if (oop_recorder()->is_real(m)) {
-        oop o = NULL;
         if (m->is_methodData()) {
           m = ((MethodData*)m)->method();
         }
@@ -545,24 +560,18 @@
           m = ((Method*)m)->method_holder();
         }
         if (m->is_klass()) {
-          o = ((Klass*)m)->class_loader();
+          append_oop_references(&oops, (Klass*)m);
         } else {
           m->print();
           ShouldNotReachHere();
         }
-        if (o != NULL && oops.find(o) == -1) {
-          oops.append(o);
-        }
       }
     }
 
   }
 
   // Add the class loader of Method* for the nmethod itself
-  oop cl = mh->method_holder()->class_loader();
-  if (cl != NULL) {
-    oops.append(cl);
-  }
+  append_oop_references(&oops, mh->method_holder());
 
   // Add any oops that we've found
   Thread* thread = Thread::current();
--- a/src/share/vm/ci/ciReplay.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/ci/ciReplay.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -31,7 +31,7 @@
 #include "memory/resourceArea.hpp"
 #include "utilities/copy.hpp"
 
-#ifdef ASSERT
+#ifndef PRODUCT
 
 // ciReplay
 
@@ -939,4 +939,4 @@
   ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
   return rec != NULL;
 }
-#endif
+#endif // PRODUCT
--- a/src/share/vm/ci/ciReplay.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/ci/ciReplay.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -32,7 +32,7 @@
 class ciReplay {
   CI_PACKAGE_ACCESS
 
-#ifdef ASSERT
+#ifndef PRODUCT
  private:
   static int replay_impl(TRAPS);
 
--- a/src/share/vm/classfile/classFileParser.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -2950,7 +2950,7 @@
 
 
 instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
-                                                    Handle class_loader,
+                                                    ClassLoaderData* loader_data,
                                                     Handle protection_domain,
                                                     KlassHandle host_klass,
                                                     GrowableArray<Handle>* cp_patches,
@@ -2964,7 +2964,7 @@
   // original class bytes.
   unsigned char *cached_class_file_bytes = NULL;
   jint cached_class_file_length;
-  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
+  Handle class_loader(THREAD, loader_data->class_loader());
   bool has_default_methods = false;
   ResourceMark rm(THREAD);
 
@@ -3005,7 +3005,7 @@
     unsigned char* ptr = cfs->buffer();
     unsigned char* end_ptr = cfs->buffer() + cfs->length();
 
-    JvmtiExport::post_class_file_load_hook(name, class_loader, protection_domain,
+    JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
                                            &ptr, &end_ptr,
                                            &cached_class_file_bytes,
                                            &cached_class_file_length);
@@ -4004,8 +4004,7 @@
   assert(k->size_helper() > 0, "layout_helper is initialized");
   if ((!RegisterFinalizersAtInit && k->has_finalizer())
       || k->is_abstract() || k->is_interface()
-      || (k->name() == vmSymbols::java_lang_Class()
-          && k->class_loader_data()->is_the_null_class_loader_data())
+      || (k->name() == vmSymbols::java_lang_Class() && k->class_loader() == NULL)
       || k->size_helper() >= FastAllocateSizeLimit) {
     // Forbid fast-path allocation.
     jint lh = Klass::instance_layout_helper(k->size_helper(), true);
--- a/src/share/vm/classfile/classFileParser.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/classFileParser.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -363,16 +363,16 @@
   // "parsed_name" is updated by this method, and is the name found
   // while parsing the stream.
   instanceKlassHandle parseClassFile(Symbol* name,
-                                     Handle class_loader,
+                                     ClassLoaderData* loader_data,
                                      Handle protection_domain,
                                      TempNewSymbol& parsed_name,
                                      bool verify,
                                      TRAPS) {
     KlassHandle no_host_klass;
-    return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD);
+    return parseClassFile(name, loader_data, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD);
   }
   instanceKlassHandle parseClassFile(Symbol* name,
-                                     Handle class_loader,
+                                     ClassLoaderData* loader_data,
                                      Handle protection_domain,
                                      KlassHandle host_klass,
                                      GrowableArray<Handle>* cp_patches,
--- a/src/share/vm/classfile/classLoader.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/classLoader.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -26,6 +26,7 @@
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -910,11 +911,11 @@
 
     // class file found, parse it
     ClassFileParser parser(stream);
-    Handle class_loader;
+    ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
     Handle protection_domain;
     TempNewSymbol parsed_name = NULL;
     instanceKlassHandle result = parser.parseClassFile(h_name,
-                                                       class_loader,
+                                                       loader_data,
                                                        protection_domain,
                                                        parsed_name,
                                                        false,
--- a/src/share/vm/classfile/classLoaderData.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/classLoaderData.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -65,13 +65,19 @@
 ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
 
 ClassLoaderData::ClassLoaderData(Handle h_class_loader) : _class_loader(h_class_loader()),
-  _metaspace(NULL), _unloading(false), _klasses(NULL),
-  _claimed(0), _jmethod_ids(NULL), _handles(NULL),
-  _deallocate_list(NULL), _next(NULL),
+  _metaspace(NULL), _unloading(false), _keep_alive(false), _klasses(NULL),
+  _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
+  _next(NULL), _dependencies(NULL),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
     // empty
 }
 
+void ClassLoaderData::init_dependencies(TRAPS) {
+  // Create empty dependencies array to add to. CMS requires this to be
+  // an oop so that it can track additions via card marks.  We think.
+  _dependencies = (oop)oopFactory::new_objectArray(2, CHECK);
+}
+
 bool ClassLoaderData::claim() {
   if (_claimed == 1) {
     return false;
@@ -86,6 +92,7 @@
   }
 
   f->do_oop(&_class_loader);
+  f->do_oop(&_dependencies);
   _handles->oops_do(f);
   if (klass_closure != NULL) {
     classes_do(klass_closure);
@@ -110,70 +117,100 @@
   ClassLoaderData * const from_cld = this;
   ClassLoaderData * const to_cld = k->class_loader_data();
 
-  // Records dependency between non-null class loaders only.
-  if (to_cld->is_the_null_class_loader_data() || from_cld->is_the_null_class_loader_data()) {
+  // Dependency to the null class loader data doesn't need to be recorded
+  // because the null class loader data never goes away.
+  if (to_cld->is_the_null_class_loader_data()) {
     return;
   }
 
-  // Check that this dependency isn't from the same or parent class_loader
-  oop to = to_cld->class_loader();
-  oop from = from_cld->class_loader();
+  oop to;
+  if (to_cld->is_anonymous()) {
+    // Anonymous class dependencies are through the mirror.
+    to = k->java_mirror();
+  } else {
+    to = to_cld->class_loader();
 
-  oop curr = from;
-  while (curr != NULL) {
-    if (curr == to) {
-      return; // this class loader is in the parent list, no need to add it.
+    // If from_cld is anonymous, even if it's class_loader is a parent of 'to'
+    // we still have to add it.  The class_loader won't keep from_cld alive.
+    if (!from_cld->is_anonymous()) {
+      // Check that this dependency isn't from the same or parent class_loader
+      oop from = from_cld->class_loader();
+
+      oop curr = from;
+      while (curr != NULL) {
+        if (curr == to) {
+          return; // this class loader is in the parent list, no need to add it.
+        }
+        curr = java_lang_ClassLoader::parent(curr);
+      }
     }
-    curr = java_lang_ClassLoader::parent(curr);
   }
 
   // It's a dependency we won't find through GC, add it. This is relatively rare
-  from_cld->add_dependency(to_cld, CHECK);
+  // Must handle over GC point.
+  Handle dependency(THREAD, to);
+  from_cld->add_dependency(dependency, CHECK);
 }
 
-bool ClassLoaderData::has_dependency(ClassLoaderData* dependency) {
-  oop loader = dependency->class_loader();
 
-  // Get objArrayOop out of the class_loader oop and see if this dependency
-  // is there.  Don't safepoint!  These are all oops.
-  // Dependency list is (oop class_loader, objArrayOop next)
-  objArrayOop ok = (objArrayOop)java_lang_ClassLoader::dependencies(class_loader());
+void ClassLoaderData::add_dependency(Handle dependency, TRAPS) {
+  // Check first if this dependency is already in the list.
+  // Save a pointer to the last to add to under the lock.
+  objArrayOop ok = (objArrayOop)_dependencies;
+  objArrayOop last = NULL;
   while (ok != NULL) {
-    if (ok->obj_at(0) == loader) {
-      return true;
+    last = ok;
+    if (ok->obj_at(0) == dependency()) {
+      // Don't need to add it
+      return;
     }
     ok = (objArrayOop)ok->obj_at(1);
   }
-  return false;
+
+  // Create a new dependency node with fields for (class_loader or mirror, next)
+  objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
+  deps->obj_at_put(0, dependency());
+
+  // Must handle over more GC points
+  objArrayHandle new_dependency(THREAD, deps);
+
+  // Add the dependency under lock
+  assert (last != NULL, "dependencies should be initialized");
+  objArrayHandle last_handle(THREAD, last);
+  locked_add_dependency(last_handle, new_dependency);
 }
 
-void ClassLoaderData::add_dependency(ClassLoaderData* dependency, TRAPS) {
-  // Minimize the number of duplicates in the list.
-  if (has_dependency(dependency)) {
-    return;
+void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle,
+                                            objArrayHandle new_dependency) {
+
+  // Have to lock and put the new dependency on the end of the dependency
+  // array so the card mark for CMS sees that this dependency is new.
+  // Can probably do this lock free with some effort.
+  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+
+  oop loader_or_mirror = new_dependency->obj_at(0);
+
+  // Since the dependencies are only added, add to the end.
+  objArrayOop end = last_handle();
+  objArrayOop last = NULL;
+  while (end != NULL) {
+    last = end;
+    // check again if another thread added it to the end.
+    if (end->obj_at(0) == loader_or_mirror) {
+      // Don't need to add it
+      return;
+    }
+    end = (objArrayOop)end->obj_at(1);
   }
-
-  // Create a new dependency node with fields for (class_loader, next)
-  objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
-  deps->obj_at_put(0, dependency->class_loader());
-
-  // Add this lock free, using compare and exchange, need barriers for GC
-  // Do the barrier first.
-  HeapWord* addr = java_lang_ClassLoader::dependencies_addr(class_loader());
-  while (true) {
-    oop old_dependency = java_lang_ClassLoader::dependencies(class_loader());
-    deps->obj_at_put(1, old_dependency);
-
-    oop newold = oopDesc::atomic_compare_exchange_oop((oop)deps, addr, old_dependency, true);
-    if (newold == old_dependency) {
-      update_barrier_set((void*)addr, (oop)deps);
-      // we won the race to add this dependency
-      break;
-    }
+  assert (last != NULL, "dependencies should be initialized");
+  // fill in the first element with the oop in new_dependency.
+  if (last->obj_at(0) == NULL) {
+    last->obj_at_put(0, new_dependency->obj_at(0));
+  } else {
+    last->obj_at_put(1, new_dependency());
   }
 }
 
-
 void ClassLoaderDataGraph::clear_claimed_marks() {
   for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
     cld->clear_claimed();
@@ -187,7 +224,7 @@
   // link the new item into the list
   _klasses = k;
 
-  if (TraceClassLoaderData && k->class_loader_data() != NULL) {
+  if (TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) {
     ResourceMark rm;
     tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: "
                   PTR_FORMAT " loader: " PTR_FORMAT " %s",
@@ -195,8 +232,7 @@
                   k->external_name(),
                   k->class_loader_data(),
                   k->class_loader(),
-                  k->class_loader() != NULL ? k->class_loader()->klass()->external_name() : "NULL"
-      );
+                  loader_name());
   }
 }
 
@@ -221,6 +257,38 @@
   ShouldNotReachHere();   // should have found this class!!
 }
 
+
+bool ClassLoaderData::is_anonymous() const {
+  Klass* k = _klasses;
+  return (_keep_alive || (k != NULL && k->oop_is_instance() &&
+          InstanceKlass::cast(k)->is_anonymous()));
+}
+
+void ClassLoaderData::unload() {
+  _unloading = true;
+
+  if (TraceClassLoaderData) {
+    ResourceMark rm;
+    tty->print("[ClassLoaderData: unload loader data "PTR_FORMAT, this);
+    tty->print(" for instance "PTR_FORMAT" of %s", class_loader(),
+               loader_name());
+    if (is_anonymous()) {
+      tty->print(" for anonymous class  "PTR_FORMAT " ", _klasses);
+    }
+    tty->print_cr("]");
+  }
+}
+
+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;
+}
+
+
 ClassLoaderData::~ClassLoaderData() {
   Metaspace *m = _metaspace;
   if (m != NULL) {
@@ -263,8 +331,8 @@
     if (_metaspace != NULL) {
       return _metaspace;
     }
-    if (class_loader() == NULL) {
-      assert(this == the_null_class_loader_data(), "Must be");
+    if (this == the_null_class_loader_data()) {
+      assert (class_loader() == NULL, "Must be");
       size_t word_size = Metaspace::first_chunk_word_size();
       set_metaspace(new Metaspace(_metaspace_lock, word_size));
     } else {
@@ -325,12 +393,19 @@
   }
 }
 
-#ifndef PRODUCT
-void ClassLoaderData::print_loader(ClassLoaderData *loader_data, outputStream* out) {
-  oop class_loader = loader_data->class_loader();
-  out->print("%s", SystemDictionary::loader_name(class_loader));
+// These anonymous class loaders are to contain classes used for JSR292
+ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(oop loader, TRAPS) {
+  // Add a new class loader data to the graph.
+  ClassLoaderData* cld = ClassLoaderDataGraph::add(NULL, loader, CHECK_NULL);
+  return cld;
 }
 
+const char* ClassLoaderData::loader_name() {
+  // Handles null class loader
+  return SystemDictionary::loader_name(class_loader());
+}
+
+#ifndef PRODUCT
 // Define to dump klasses
 #undef CLD_DUMP_KLASSES
 
@@ -338,8 +413,7 @@
   ResourceMark rm;
   out->print("ClassLoaderData CLD: "PTR_FORMAT", loader: "PTR_FORMAT", loader_klass: "PTR_FORMAT" %s {",
       this, class_loader(),
-      class_loader() != NULL ? class_loader()->klass() : NULL,
-      class_loader() != NULL ? class_loader()->klass()->external_name() : "NULL");
+      class_loader() != NULL ? class_loader()->klass() : NULL, loader_name());
   if (claimed()) out->print(" claimed ");
   if (is_unloading()) out->print(" unloading ");
   out->print(" handles " INTPTR_FORMAT, handles());
@@ -373,8 +447,8 @@
 void ClassLoaderData::verify() {
   oop cl = class_loader();
 
-  guarantee(this == class_loader_data(cl), "Must be the same");
-  guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data(), "must be");
+  guarantee(this == class_loader_data(cl) || is_anonymous(), "Must be the same");
+  guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_anonymous(), "must be");
 
   // Verify the integrity of the allocated space.
   if (metaspace_or_null() != NULL) {
@@ -387,6 +461,7 @@
   }
 }
 
+
 // GC root of class loader data created.
 ClassLoaderData* ClassLoaderDataGraph::_head = NULL;
 ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
@@ -395,19 +470,25 @@
 
 // Add a new class loader data node to the list.  Assign the newly created
 // ClassLoaderData into the java/lang/ClassLoader object as a hidden field
-ClassLoaderData* ClassLoaderDataGraph::add(ClassLoaderData** cld_addr, Handle loader_data) {
+ClassLoaderData* ClassLoaderDataGraph::add(ClassLoaderData** cld_addr, Handle loader, TRAPS) {
   // Not assigned a class loader data yet.
   // Create one.
   ClassLoaderData* *list_head = &_head;
   ClassLoaderData* next = _head;
-  ClassLoaderData* cld = new ClassLoaderData(loader_data);
+  ClassLoaderData* cld = new ClassLoaderData(loader);
 
-  // First, Atomically set it.
-  ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL);
-  if (old != NULL) {
-    delete cld;
-    // Returns the data.
-    return old;
+  if (cld_addr != NULL) {
+    // First, Atomically set it
+    ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL);
+    if (old != NULL) {
+      delete cld;
+      // Returns the data.
+      return old;
+    }
+  } else {
+    // Disallow unloading for this CLD during initialization if there is no
+    // class_loader oop to link this to.
+    cld->set_keep_alive(true);
   }
 
   // We won the race, and therefore the task of adding the data to the list of
@@ -417,16 +498,22 @@
     ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next);
     if (exchanged == next) {
       if (TraceClassLoaderData) {
+        ResourceMark rm;
         tty->print("[ClassLoaderData: ");
         tty->print("create class loader data "PTR_FORMAT, cld);
-        tty->print(" for instance "PTR_FORMAT" of ", cld->class_loader());
-        loader_data->klass()->name()->print_symbol_on(tty);
+        tty->print(" for instance "PTR_FORMAT" of %s", cld->class_loader(),
+                   cld->loader_name());
         tty->print_cr("]");
       }
+      // Create dependencies after the CLD is added to the list.  Otherwise,
+      // the GC GC will not find the CLD and the _class_loader field will
+      // not be updated.
+      cld->init_dependencies(CHECK_NULL);
       return cld;
     }
     next = exchanged;
   } while (true);
+
 }
 
 void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
@@ -435,9 +522,19 @@
   }
 }
 
+void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    if (cld->keep_alive()) {
+      cld->oops_do(f, klass_closure, must_claim);
+    }
+  }
+}
+
 void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
   if (ClassUnloading) {
     ClassLoaderData::the_null_class_loader_data()->oops_do(f, klass_closure, must_claim);
+    // keep any special CLDs alive.
+    ClassLoaderDataGraph::keep_alive_oops_do(f, klass_closure, must_claim);
   } else {
     ClassLoaderDataGraph::oops_do(f, klass_closure, must_claim);
   }
@@ -516,9 +613,10 @@
 }
 #endif // PRODUCT
 
+
 // Move class loader data from main list to the unloaded list for unloading
 // and deallocation later.
-bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive) {
+bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) {
   ClassLoaderData* data = _head;
   ClassLoaderData* prev = NULL;
   bool seen_dead_loader = false;
@@ -527,8 +625,7 @@
   bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
   MetadataOnStackMark md_on_stack;
   while (data != NULL) {
-    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->keep_alive() || data->is_alive(is_alive_closure)) {
       if (has_redefined_a_class) {
         data->classes_do(InstanceKlass::purge_previous_versions);
       }
@@ -539,13 +636,7 @@
     }
     seen_dead_loader = true;
     ClassLoaderData* dead = data;
-    dead->mark_for_unload();
-    if (TraceClassLoaderData) {
-      tty->print("[ClassLoaderData: unload loader data "PTR_FORMAT, dead);
-      tty->print(" for instance "PTR_FORMAT" of ", dead->class_loader());
-      dead->class_loader()->klass()->name()->print_symbol_on(tty);
-      tty->print_cr("]");
-    }
+    dead->unload();
     data = data->next();
     // Remove from loader list.
     if (prev != NULL) {
--- a/src/share/vm/classfile/classLoaderData.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/classLoaderData.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -62,13 +62,14 @@
   // CMS support.
   static ClassLoaderData* _saved_head;
 
-  static ClassLoaderData* add(ClassLoaderData** loader_data_addr, Handle class_loader);
+  static ClassLoaderData* add(ClassLoaderData** loader_data_addr, Handle class_loader, TRAPS);
  public:
-  static ClassLoaderData* find_or_create(Handle class_loader);
+  static ClassLoaderData* find_or_create(Handle class_loader, TRAPS);
   static void purge();
   static void clear_claimed_marks();
   static void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim);
   static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
+  static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
   static void classes_do(KlassClosure* klass_closure);
   static bool do_unloading(BoolObjectClosure* is_alive);
 
@@ -101,10 +102,13 @@
 
   oop _class_loader;       // oop used to uniquely identify a class loader
                            // class loader or a canonical class path
+  oop _dependencies;       // oop to hold dependencies from this class loader
+                           // data to others.
   Metaspace * _metaspace;  // Meta-space where meta-data defined by the
                            // classes in the class loader are allocated.
   Mutex* _metaspace_lock;  // Locks the metaspace for allocations and setup.
   bool _unloading;         // true if this class loader goes away
+  bool _keep_alive;        // if this CLD can be unloaded for anonymous loaders
   volatile int _claimed;   // true if claimed, for example during GC traces.
                            // To avoid applying oop closure more than once.
                            // Has to be an int because we cas it.
@@ -129,8 +133,8 @@
   static Metaspace* _ro_metaspace;
   static Metaspace* _rw_metaspace;
 
-  bool has_dependency(ClassLoaderData* cld);
-  void add_dependency(ClassLoaderData* to_loader_data, TRAPS);
+  void add_dependency(Handle dependency, TRAPS);
+  void locked_add_dependency(objArrayHandle last, objArrayHandle new_dependency);
 
   void set_next(ClassLoaderData* next) { _next = next; }
   ClassLoaderData* next() const        { return _next; }
@@ -150,7 +154,9 @@
   bool claimed() const          { return _claimed == 1; }
   bool claim();
 
-  void mark_for_unload()        { _unloading = true; }
+  void unload();
+  bool keep_alive() const       { return _keep_alive; }
+  bool is_alive(BoolObjectClosure* is_alive_closure) const;
 
   void classes_do(void f(InstanceKlass*));
 
@@ -168,6 +174,8 @@
     return _the_null_class_loader_data;
   }
 
+  bool is_anonymous() const;
+
   static void init_null_class_loader_data() {
     assert(_the_null_class_loader_data == NULL, "cannot initialize twice");
     assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice");
@@ -194,6 +202,9 @@
     assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded");
     return _unloading;
   }
+  // Anonymous class loader data doesn't have anything to keep them from
+  // being unloaded during parsing the anonymous class.
+  void set_keep_alive(bool value) { _keep_alive = value; }
 
   unsigned int identity_hash() {
     return _class_loader == NULL ? 0 : _class_loader->identity_hash();
@@ -211,15 +222,18 @@
   void print_value_on(outputStream* out) const PRODUCT_RETURN;
   void dump(outputStream * const out) PRODUCT_RETURN;
   void verify();
+  const char* loader_name();
 
   jobject add_handle(Handle h);
   void add_class(Klass* k);
   void remove_class(Klass* k);
   void record_dependency(Klass* to, TRAPS);
+  void init_dependencies(TRAPS);
 
   void add_to_deallocate_list(Metadata* m);
 
   static ClassLoaderData* class_loader_data(oop loader);
+  static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS);
   static void print_loader(ClassLoaderData *loader_data, outputStream *out);
 
   // CDS support
--- a/src/share/vm/classfile/classLoaderData.inline.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/classLoaderData.inline.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -33,7 +33,7 @@
 }
 
 
-inline ClassLoaderData *ClassLoaderDataGraph::find_or_create(Handle loader) {
+inline ClassLoaderData *ClassLoaderDataGraph::find_or_create(Handle loader, TRAPS) {
   assert(loader() != NULL,"Must be a class loader");
   // Gets the class loader data out of the java/lang/ClassLoader object, if non-null
   // it's already in the loader_data, so no need to add
@@ -42,5 +42,5 @@
   if (loader_data_id) {
      return loader_data_id;
   }
-  return ClassLoaderDataGraph::add(loader_data_addr, loader);
+  return ClassLoaderDataGraph::add(loader_data_addr, loader, THREAD);
 }
--- a/src/share/vm/classfile/dictionary.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/dictionary.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -580,7 +580,7 @@
       // class loader must be present;  a null class loader is the
       // boostrap loader
       guarantee(loader_data != NULL || DumpSharedSpaces ||
-                loader_data->is_the_null_class_loader_data() ||
+                loader_data->class_loader() == NULL ||
                 loader_data->class_loader()->is_instance(),
                 "checking type of class_loader");
       e->verify();
--- a/src/share/vm/classfile/javaClasses.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/javaClasses.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -2544,8 +2544,8 @@
 
 void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) {
   assert(is_instance(mname), "wrong type");
-#ifdef ASSERT
   // check the type of the vmtarget
+  oop dependency = NULL;
   if (ref != NULL) {
     switch (flags(mname) & (MN_IS_METHOD |
                             MN_IS_CONSTRUCTOR |
@@ -2553,28 +2553,21 @@
     case MN_IS_METHOD:
     case MN_IS_CONSTRUCTOR:
       assert(ref->is_method(), "should be a method");
+      dependency = ((Method*)ref)->method_holder()->java_mirror();
       break;
     case MN_IS_FIELD:
       assert(ref->is_klass(), "should be a class");
+      dependency = ((Klass*)ref)->java_mirror();
       break;
     default:
       ShouldNotReachHere();
     }
   }
-#endif //ASSERT
   mname->address_field_put(_vmtarget_offset, (address)ref);
-  oop loader = NULL;
-  if (ref != NULL) {
-    if (ref->is_klass()) {
-      loader = ((Klass*)ref)->class_loader();
-    } else if (ref->is_method()) {
-      loader = ((Method*)ref)->method_holder()->class_loader();
-    } else {
-      ShouldNotReachHere();
-    }
-  }
-  // Add a reference to the loader to ensure the metadata is kept alive
-  mname->obj_field_put(_vmloader_offset, loader);
+  // Add a reference to the loader (actually mirror because anonymous classes will not have
+  // distinct loaders) to ensure the metadata is kept alive
+  // This mirror may be different than the one in clazz field.
+  mname->obj_field_put(_vmloader_offset, dependency);
 }
 
 intptr_t java_lang_invoke_MemberName::vmindex(oop mname) {
@@ -2739,7 +2732,6 @@
 
 bool java_lang_ClassLoader::offsets_computed = false;
 int  java_lang_ClassLoader::_loader_data_offset = -1;
-int  java_lang_ClassLoader::_dependencies_offset = -1;
 int  java_lang_ClassLoader::parallelCapable_offset = -1;
 
 ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
@@ -2751,18 +2743,6 @@
   return *java_lang_ClassLoader::loader_data_addr(loader);
 }
 
-oop java_lang_ClassLoader::dependencies(oop loader) {
-  return loader->obj_field(_dependencies_offset);
-}
-
-HeapWord* java_lang_ClassLoader::dependencies_addr(oop loader) {
-  if (UseCompressedOops) {
-    return (HeapWord*)loader->obj_field_addr<narrowOop>(_dependencies_offset);
-  } else {
-    return (HeapWord*)loader->obj_field_addr<oop>(_dependencies_offset);
-  }
-}
-
 void java_lang_ClassLoader::compute_offsets() {
   assert(!offsets_computed, "offsets should be initialized only once");
   offsets_computed = true;
--- a/src/share/vm/classfile/javaClasses.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -1125,8 +1125,7 @@
 // Interface to java.lang.ClassLoader objects
 
 #define CLASSLOADER_INJECTED_FIELDS(macro)                            \
-  macro(java_lang_ClassLoader, loader_data,  intptr_signature, false) \
-  macro(java_lang_ClassLoader, dependencies, object_signature, false)
+  macro(java_lang_ClassLoader, loader_data,  intptr_signature, false)
 
 class java_lang_ClassLoader : AllStatic {
  private:
@@ -1135,7 +1134,6 @@
    hc_parent_offset = 0
   };
   static int _loader_data_offset;
-  static int _dependencies_offset;
   static bool offsets_computed;
   static int parent_offset;
   static int parallelCapable_offset;
@@ -1146,9 +1144,6 @@
   static ClassLoaderData** loader_data_addr(oop loader);
   static ClassLoaderData* loader_data(oop loader);
 
-  static oop  dependencies(oop loader);
-  static HeapWord* dependencies_addr(oop loader);
-
   static oop parent(oop loader);
   static bool isAncestor(oop loader, oop cl);
 
--- a/src/share/vm/classfile/loaderConstraints.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/loaderConstraints.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -118,7 +118,7 @@
                      probe->name()->as_C_string());
           for (int i = 0; i < probe->num_loaders(); i++) {
             tty->print_cr("[   [%d]: %s", i,
-                          SystemDictionary::loader_name(probe->loader_data(i)));
+                          probe->loader_data(i)->loader_name());
           }
         }
       }
@@ -129,7 +129,7 @@
             if (TraceLoaderConstraints) {
               ResourceMark rm;
               tty->print_cr("[Purging loader %s from constraint for name %s",
-                          SystemDictionary::loader_name(probe->loader_data(n)),
+                            probe->loader_data(n)->loader_name(),
                             probe->name()->as_C_string()
                             );
             }
@@ -145,7 +145,7 @@
               tty->print_cr("[New loader list:");
               for (int i = 0; i < probe->num_loaders(); i++) {
                 tty->print_cr("[   [%d]: %s", i,
-                            SystemDictionary::loader_name(probe->loader_data(i)));
+                              probe->loader_data(i)->loader_name());
               }
             }
 
@@ -400,7 +400,7 @@
 
     for (int i = 0; i < p1->num_loaders(); i++) {
       tty->print_cr("[   [%d]: %s", i,
-                    SystemDictionary::loader_name(p1->loader_data(i)));
+                    p1->loader_data(i)->loader_name());
     }
     if (p1->klass() == NULL) {
       tty->print_cr("[... and setting class object]");
--- a/src/share/vm/classfile/systemDictionary.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -106,9 +106,9 @@
 }
 
 
-ClassLoaderData* SystemDictionary::register_loader(Handle class_loader) {
+ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, TRAPS) {
   if (class_loader() == NULL) return ClassLoaderData::the_null_class_loader_data();
-  return ClassLoaderDataGraph::find_or_create(class_loader);
+  return ClassLoaderDataGraph::find_or_create(class_loader, CHECK_NULL);
 }
 
 // ----------------------------------------------------------------------------
@@ -591,7 +591,7 @@
   // UseNewReflection
   // Fix for 4474172; see evaluation for more details
   class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
-  ClassLoaderData *loader_data = register_loader(class_loader);
+  ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
 
   // Do lookup to see if class already exist and the protection domain
   // has the right access
@@ -888,7 +888,7 @@
   // of the call to resolve_instance_class_or_null().
   // See evaluation 6790209 and 4474172 for more details.
   class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
-  ClassLoaderData* loader_data = register_loader(class_loader);
+  ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL);
 
   unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
   int d_index = dictionary()->hash_to_index(d_hash);
@@ -948,6 +948,18 @@
                                       TRAPS) {
   TempNewSymbol parsed_name = NULL;
 
+  ClassLoaderData* loader_data;
+  if (host_klass.not_null()) {
+    // Create a new CLD for anonymous class, that uses the same class loader
+    // as the host_klass
+    assert(EnableInvokeDynamic, "");
+    guarantee(host_klass->class_loader() == class_loader(), "should be the same");
+    loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
+    loader_data->record_dependency(host_klass(), CHECK_NULL);
+  } else {
+    loader_data = ClassLoaderData::class_loader_data(class_loader());
+  }
+
   // Parse the stream. Note that we do this even though this klass might
   // already be present in the SystemDictionary, otherwise we would not
   // throw potential ClassFormatErrors.
@@ -959,7 +971,7 @@
   //   java.lang.Object through resolve_or_fail, not this path.
 
   instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
-                                                             class_loader,
+                                                             loader_data,
                                                              protection_domain,
                                                              host_klass,
                                                              cp_patches,
@@ -973,8 +985,6 @@
   // Parsed name could be null if we threw an error before we got far
   // enough along to parse it -- in that case, there is nothing to clean up.
   if (parsed_name != NULL) {
-    ClassLoaderData* loader_data = class_loader_data(class_loader);
-
     unsigned int p_hash = placeholders()->compute_hash(parsed_name,
                                                        loader_data);
     int p_index = placeholders()->hash_to_index(p_hash);
@@ -987,9 +997,8 @@
 
   if (host_klass.not_null() && k.not_null()) {
     assert(EnableInvokeDynamic, "");
+    k->set_host_klass(host_klass());
     // If it's anonymous, initialize it now, since nobody else will.
-    k->class_loader_data()->record_dependency(host_klass(), CHECK_NULL);
-    k->set_host_klass(host_klass());
 
     {
       MutexLocker mu_r(Compile_lock, THREAD);
@@ -1002,11 +1011,11 @@
     }
 
     // Rewrite and patch constant pool here.
-    k->link_class(THREAD);
+    k->link_class(CHECK_NULL);
     if (cp_patches != NULL) {
       k->constants()->patch_resolved_references(cp_patches);
     }
-    k->eager_initialize(THREAD);
+    k->eager_initialize(CHECK_NULL);
 
     // notify jvmti
     if (JvmtiExport::should_post_class_load()) {
@@ -1039,7 +1048,7 @@
     DoObjectLock = false;
   }
 
-  ClassLoaderData* loader_data = register_loader(class_loader);
+  ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL);
 
   // Make sure we are synchronized on the class loader before we proceed
   Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
@@ -1059,7 +1068,7 @@
   //   java.lang.Object through resolve_or_fail, not this path.
 
   instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
-                                                             class_loader,
+                                                             loader_data,
                                                              protection_domain,
                                                              parsed_name,
                                                              verify,
@@ -2343,6 +2352,7 @@
 
 // Helper for unpacking the return value from linkMethod and linkCallSite.
 static methodHandle unpack_method_and_appendix(Handle mname,
+                                               KlassHandle accessing_klass,
                                                objArrayHandle appendix_box,
                                                Handle* appendix_result,
                                                TRAPS) {
@@ -2361,6 +2371,12 @@
     #endif //PRODUCT
       }
       (*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.
+      // FIXME: the appendix might also preserve this dependency.
+      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);
     }
   }
@@ -2405,7 +2421,7 @@
                          &args, CHECK_(empty));
   Handle mname(THREAD, (oop) result.get_jobject());
   (*method_type_result) = method_type;
-  return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD);
+  return unpack_method_and_appendix(mname, accessing_klass, appendix_box, appendix_result, THREAD);
 }
 
 
@@ -2596,7 +2612,7 @@
                          &args, CHECK_(empty));
   Handle mname(THREAD, (oop) result.get_jobject());
   (*method_type_result) = method_type;
-  return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD);
+  return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
 }
 
 // Since the identity hash code for symbols changes when the symbols are
--- a/src/share/vm/classfile/systemDictionary.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -471,7 +471,7 @@
   static void compute_java_system_loader(TRAPS);
 
   // Register a new class loader
-  static ClassLoaderData* register_loader(Handle class_loader);
+  static ClassLoaderData* register_loader(Handle class_loader, TRAPS);
 private:
   // Mirrors for primitive classes (created eagerly)
   static oop check_mirror(oop m) {
@@ -531,7 +531,7 @@
             InstanceKlass::cast((loader)->klass())->name()->as_C_string() );
   }
   static const char* loader_name(ClassLoaderData* loader_data) {
-    return (loader_data->is_the_null_class_loader_data() ? "<bootloader>" :
+    return (loader_data->class_loader() == NULL ? "<bootloader>" :
             InstanceKlass::cast((loader_data->class_loader())->klass())->name()->as_C_string() );
   }
 
--- a/src/share/vm/compiler/compileBroker.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/compiler/compileBroker.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -269,10 +269,12 @@
                              const char* comment,
                              bool is_blocking) {
   assert(!_lock->is_locked(), "bad locking");
+  InstanceKlass* holder = method->method_holder();
 
   _compile_id = compile_id;
   _method = method();
-  _method_loader = JNIHandles::make_global(_method->method_holder()->class_loader());
+  _method_holder = JNIHandles::make_global(
+        holder->is_anonymous() ? holder->java_mirror(): holder->class_loader());
   _osr_bci = osr_bci;
   _is_blocking = is_blocking;
   _comp_level = comp_level;
@@ -283,7 +285,7 @@
   _code_handle = NULL;
 
   _hot_method = NULL;
-  _hot_method_loader = NULL;
+  _hot_method_holder = NULL;
   _hot_count = hot_count;
   _time_queued = 0;  // tidy
   _comment = comment;
@@ -295,8 +297,12 @@
         _hot_method = _method;
       } else {
         _hot_method = hot_method();
+        // only add loader or mirror if different from _method_holder
+        InstanceKlass* hot_holder = hot_method->method_holder();
+        _hot_method_holder = JNIHandles::make_global(
+               hot_holder->is_anonymous() ? hot_holder->java_mirror() :
+                                            hot_holder->class_loader());
       }
-      _hot_method_loader = JNIHandles::make_global(_hot_method->method_holder()->class_loader());
     }
   }
 
@@ -321,8 +327,8 @@
 void CompileTask::free() {
   set_code(NULL);
   assert(!_lock->is_locked(), "Should not be locked when freed");
-  JNIHandles::destroy_global(_method_loader);
-  JNIHandles::destroy_global(_hot_method_loader);
+  JNIHandles::destroy_global(_method_holder);
+  JNIHandles::destroy_global(_hot_method_holder);
 }
 
 
--- a/src/share/vm/compiler/compileBroker.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/compiler/compileBroker.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -43,7 +43,7 @@
   Monitor*     _lock;
   uint         _compile_id;
   Method*      _method;
-  jobject      _method_loader;
+  jobject      _method_holder;
   int          _osr_bci;
   bool         _is_complete;
   bool         _is_success;
@@ -56,7 +56,7 @@
   // Fields used for logging why the compilation was initiated:
   jlong        _time_queued;  // in units of os::elapsed_counter()
   Method*      _hot_method;   // which method actually triggered this task
-  jobject      _hot_method_loader;
+  jobject      _hot_method_holder;
   int          _hot_count;    // information about its invocation counter
   const char*  _comment;      // more info about the task
 
--- a/src/share/vm/memory/metachunk.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/metachunk.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -123,9 +123,7 @@
 
   void assert_is_mangled() const {/* Don't check "\*/}
 
-#ifdef ASSERT
-  void mangle();
-#endif // ASSERT
+  NOT_PRODUCT(void mangle();)
 
   void print_on(outputStream* st) const;
   void verify();
--- a/src/share/vm/memory/metaspace.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/metaspace.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -108,7 +108,6 @@
   size_t Metablock::_overhead = 0;
 #endif
 
-
 // Pointer to list of Metachunks.
 class ChunkList VALUE_OBJ_CLASS_SPEC {
   // List of free chunks
@@ -325,10 +324,12 @@
   bool expand_by(size_t words, bool pre_touch = false);
   bool shrink_by(size_t words);
 
+#ifdef ASSERT
   // Debug support
   static void verify_virtual_space_total();
   static void verify_virtual_space_count();
   void mangle();
+#endif
 
   void print_on(outputStream* st) const;
 };
@@ -621,8 +622,8 @@
   void locked_print_chunks_in_use_on(outputStream* st) const;
 
   void verify();
+  NOT_PRODUCT(void mangle_freed_chunks();)
 #ifdef ASSERT
-  void mangle_freed_chunks();
   void verify_allocation_total();
 #endif
 };
@@ -711,7 +712,7 @@
                bottom(), top(), end(), word_size());
 }
 
-#ifdef ASSERT
+#ifndef PRODUCT
 void Metachunk::mangle() {
   // Mangle the payload of the chunk and not the links that
   // maintain list of chunks.
@@ -719,7 +720,7 @@
   size_t word_size = capacity_word_size() - overhead();
   Copy::fill_to_words(start, word_size, metadata_chunk_initialize);
 }
-#endif // ASSERT
+#endif // PRODUCT
 
 void Metachunk::verify() {
 #ifdef ASSERT
@@ -917,10 +918,12 @@
            vs->high_boundary());
 }
 
+#ifdef ASSERT
 void VirtualSpaceNode::mangle() {
   size_t word_size = capacity_words_in_vs();
   Copy::fill_to_words((HeapWord*) low(), word_size, 0xf1f1f1f1);
 }
+#endif // ASSERT
 
 // VirtualSpaceList methods
 // Space allocated from the VirtualSpace
@@ -1985,16 +1988,14 @@
     locked_print_chunks_in_use_on(gclog_or_tty);
   }
 
+  // Mangle freed memory.
+  NOT_PRODUCT(mangle_freed_chunks();)
+
   // Have to update before the chunks_in_use lists are emptied
   // below.
   chunk_manager->inc_free_chunks_total(sum_capacity_in_chunks_in_use(),
                                        sum_count_in_chunks_in_use());
 
-#ifdef ASSERT
-  // Mangle freed memory.
-  mangle_freed_chunks();
-#endif // ASSERT
-
   // Add all the chunks in use by this space manager
   // to the global list of free chunks.
 
@@ -2273,7 +2274,7 @@
                 " waste " SIZE_FORMAT, curr_total, used, free, capacity, waste);
 }
 
-#ifdef ASSERT
+#ifndef PRODUCT
 void SpaceManager::mangle_freed_chunks() {
   for (ChunkIndex index = SmallIndex;
        index < NumberOfInUseLists;
@@ -2291,11 +2292,16 @@
     }
   }
 }
-#endif // ASSERT
+#endif // PRODUCT
 
 
 // MetaspaceAux
 
+size_t MetaspaceAux::used_in_bytes() {
+  return (Metaspace::class_space_list()->used_words_sum() +
+          Metaspace::space_list()->used_words_sum()) * BytesPerWord;
+}
+
 size_t MetaspaceAux::used_in_bytes(Metaspace::MetadataType mdtype) {
   size_t used = 0;
   ClassLoaderDataGraphMetaspaceIterator iter;
@@ -2324,6 +2330,11 @@
 // The total words available for metadata allocation.  This
 // uses Metaspace capacity_words() which is the total words
 // in chunks allocated for a Metaspace.
+size_t MetaspaceAux::capacity_in_bytes() {
+  return (Metaspace::class_space_list()->capacity_words_sum() +
+          Metaspace::space_list()->capacity_words_sum()) * BytesPerWord;
+}
+
 size_t MetaspaceAux::capacity_in_bytes(Metaspace::MetadataType mdtype) {
   size_t capacity = free_chunks_total(mdtype);
   ClassLoaderDataGraphMetaspaceIterator iter;
@@ -2336,6 +2347,11 @@
   return capacity * BytesPerWord;
 }
 
+size_t MetaspaceAux::reserved_in_bytes() {
+  return (Metaspace::class_space_list()->virtual_space_total() +
+          Metaspace::space_list()->virtual_space_total()) * BytesPerWord;
+}
+
 size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) {
   size_t reserved = (mdtype == Metaspace::ClassType) ?
                        Metaspace::class_space_list()->virtual_space_total() :
--- a/src/share/vm/memory/metaspace.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/metaspace.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -160,25 +160,16 @@
 
  public:
   // Total of space allocated to metadata in all Metaspaces
-  static size_t used_in_bytes() {
-    return used_in_bytes(Metaspace::ClassType) +
-           used_in_bytes(Metaspace::NonClassType);
-  }
+  static size_t used_in_bytes();
 
   // Total of available space in all Metaspaces
   // Total of capacity allocated to all Metaspaces.  This includes
   // space in Metachunks not yet allocated and in the Metachunk
   // freelist.
-  static size_t capacity_in_bytes() {
-    return capacity_in_bytes(Metaspace::ClassType) +
-           capacity_in_bytes(Metaspace::NonClassType);
-  }
+  static size_t capacity_in_bytes();
 
   // Total space reserved in all Metaspaces
-  static size_t reserved_in_bytes() {
-    return reserved_in_bytes(Metaspace::ClassType) +
-           reserved_in_bytes(Metaspace::NonClassType);
-  }
+  static size_t reserved_in_bytes();
 
   static size_t min_chunk_size();
 
--- a/src/share/vm/memory/universe.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/universe.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -407,6 +407,10 @@
     assert(i == _fullgc_alot_dummy_array->length(), "just checking");
   }
   #endif
+
+  // Initialize dependency array for null class loader
+  ClassLoaderData::the_null_class_loader_data()->init_dependencies(CHECK);
+
 }
 
 // CDS support for patching vtables in metadata in the shared archive.
--- a/src/share/vm/oops/constantPool.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/constantPool.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -340,9 +340,7 @@
       do_resolve = this_oop->tag_at(which).is_unresolved_klass();
       if (do_resolve) {
         ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
-        if (!this_key->is_the_null_class_loader_data()) {
-          this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
-        }
+        this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
         this_oop->klass_at_put(which, k());
       }
     }
--- a/src/share/vm/oops/klass.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/klass.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -373,29 +373,22 @@
   debug_only(verify();)
 }
 
-void Klass::remove_from_sibling_list() {
-  // remove receiver from sibling list
-  InstanceKlass* super = superklass();
-  assert(super != NULL || this == SystemDictionary::Object_klass(), "should have super");
-  if (super == NULL) return;        // special case: class Object
-  if (super->subklass() == this) {
-    // first subklass
-    super->set_subklass(_next_sibling);
-  } else {
-    Klass* sib = super->subklass();
-    while (sib->next_sibling() != this) {
-      sib = sib->next_sibling();
-    };
-    sib->set_next_sibling(_next_sibling);
-  }
-}
-
 bool Klass::is_loader_alive(BoolObjectClosure* is_alive) {
   assert(is_metadata(), "p is not meta-data");
   assert(ClassLoaderDataGraph::contains((address)this), "is in the metaspace");
+
+#ifdef ASSERT
   // The class is alive iff the class loader is alive.
   oop loader = class_loader();
-  return (loader == NULL) || is_alive->do_object_b(loader);
+  bool loader_alive = (loader == NULL) || is_alive->do_object_b(loader);
+#endif // ASSERT
+
+  // The class is alive if it's mirror is alive (which should be marked if the
+  // loader is alive) unless it's an anoymous class.
+  bool mirror_alive = is_alive->do_object_b(java_mirror());
+  assert(!mirror_alive || loader_alive, "loader must be alive if the mirror is"
+                        " but not the other way around with anonymous classes");
+  return mirror_alive;
 }
 
 void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive) {
@@ -416,10 +409,10 @@
     Klass* sub = current->subklass_oop();
     while (sub != NULL && !sub->is_loader_alive(is_alive)) {
 #ifndef PRODUCT
-        if (TraceClassUnloading && WizardMode) {
-          ResourceMark rm;
+      if (TraceClassUnloading && WizardMode) {
+        ResourceMark rm;
         tty->print_cr("[Unlinking class (subclass) %s]", sub->external_name());
-        }
+      }
 #endif
       sub = sub->next_sibling_oop();
     }
@@ -431,16 +424,16 @@
     // Find and set the first alive sibling
     Klass* sibling = current->next_sibling_oop();
     while (sibling != NULL && !sibling->is_loader_alive(is_alive)) {
-          if (TraceClassUnloading && WizardMode) {
-            ResourceMark rm;
+      if (TraceClassUnloading && WizardMode) {
+        ResourceMark rm;
         tty->print_cr("[Unlinking class (sibling) %s]", sibling->external_name());
-          }
+      }
       sibling = sibling->next_sibling_oop();
-      }
+    }
     current->set_next_sibling(sibling);
     if (sibling != NULL) {
       stack.push(sibling);
-}
+    }
 
     // Clean the implementors list and method data.
     if (current->oop_is_instance()) {
@@ -554,7 +547,11 @@
     InstanceKlass* ik = (InstanceKlass*) this;
     if (ik->is_anonymous()) {
       assert(EnableInvokeDynamic, "");
-      intptr_t hash = ik->java_mirror()->identity_hash();
+      intptr_t hash = 0;
+      if (ik->java_mirror() != NULL) {
+        // java_mirror might not be created yet, return 0 as hash.
+        hash = ik->java_mirror()->identity_hash();
+      }
       char     hash_buf[40];
       sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
       size_t   hash_len = strlen(hash_buf);
--- a/src/share/vm/oops/klass.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/klass.hpp	Thu Nov 29 16:50:29 2012 -0500
@@ -267,7 +267,6 @@
   Klass* subklass() const;
   Klass* next_sibling() const;
   void append_to_sibling_list();           // add newly created receiver to superklass' subklass list
-  void remove_from_sibling_list();         // remove receiver from sibling list
 
   void set_next_link(Klass* k) { _next_link = k; }
   Klass* next_link() const { return _next_link; }   // The next klass defined by the class loader.
@@ -581,8 +580,8 @@
   // garbage collection support
   virtual void oops_do(OopClosure* cl);
 
-  // Checks if the class loader is alive.
-  // Iff the class loader is alive the Klass is considered alive.
+  // Iff the class loader (or mirror for anonymous classes) is alive the
+  // Klass is considered alive.
   // The is_alive closure passed in depends on the Garbage Collector used.
   bool is_loader_alive(BoolObjectClosure* is_alive);
 
--- a/src/share/vm/oops/objArrayKlass.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/objArrayKlass.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -88,11 +88,6 @@
       }
       if (!supers_exist) {
         // Oops.  Not allocated yet.  Back out, allocate it, and retry.
-#ifndef PRODUCT
-        if (WizardMode) {
-          tty->print_cr("Must retry array klass creation for depth %d",n);
-        }
-#endif
         KlassHandle ek;
         {
           MutexUnlocker mu(MultiArray_lock);
--- a/src/share/vm/prims/unsafe.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/prims/unsafe.cpp	Thu Nov 29 16:50:29 2012 -0500
@@ -996,7 +996,7 @@
 // not just a literal string.  For such ldc instructions, the verifier uses the
 // type Object instead of String, if the loaded constant is not in fact a String.
 
-static oop
+static instanceKlassHandle
 Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
                                  jclass host_class, jbyteArray data, jobjectArray cp_patches_jh,
                                  HeapWord* *temp_alloc,
@@ -1073,32 +1073,39 @@
     anon_klass = instanceKlassHandle(THREAD, anonk);
   }
 
-  // let caller initialize it as needed...
-
-  return anon_klass->java_mirror();
+  return anon_klass;
 }
 
 UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh))
 {
+  instanceKlassHandle anon_klass;
+  jobject res_jh = NULL;
+
   UnsafeWrapper("Unsafe_DefineAnonymousClass");
   ResourceMark rm(THREAD);
 
   HeapWord* temp_alloc = NULL;
 
-  jobject res_jh = NULL;
-
-  { oop res_oop = Unsafe_DefineAnonymousClass_impl(env,
-                                                   host_class, data, cp_patches_jh,
+  anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data,
+                                                cp_patches_jh,
                                                    &temp_alloc, THREAD);
-    if (res_oop != NULL)
-      res_jh = JNIHandles::make_local(env, res_oop);
-  }
+  if (anon_klass() != NULL)
+    res_jh = JNIHandles::make_local(env, anon_klass->java_mirror());
 
   // try/finally clause:
   if (temp_alloc != NULL) {
     FREE_C_HEAP_ARRAY(HeapWord, temp_alloc, mtInternal);
   }
 
+  // The anonymous class loader data has been artificially been kept alive to
+  // this point.   The mirror and any instances of this class have to keep
+  // it alive afterwards.
+  if (anon_klass() != NULL) {
+    anon_klass->class_loader_data()->set_keep_alive(false);
+  }
+
+  // let caller initialize it as needed...
+
   return (jclass) res_jh;
 }
 UNSAFE_END