hotspot/src/share/vm/memory/metaspaceShared.cpp
changeset 47103 a993ec29ec75
parent 46989 119e1e88cf15
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Aug 30 19:18:22 2017 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Mon Aug 28 15:34:04 2017 -0700
@@ -374,25 +374,63 @@
 // Global object for holding classes that have been loaded.  Since this
 // is run at a safepoint just before exit, this is the entire set of classes.
 static GrowableArray<Klass*>* _global_klass_objects;
+
+static void collect_array_classes(Klass* k) {
+  _global_klass_objects->append_if_missing(k);
+  if (k->is_array_klass()) {
+    // Add in the array classes too
+    ArrayKlass* ak = ArrayKlass::cast(k);
+    Klass* h = ak->higher_dimension();
+    if (h != NULL) {
+      h->array_klasses_do(collect_array_classes);
+    }
+  }
+}
+
 class CollectClassesClosure : public KlassClosure {
   void do_klass(Klass* k) {
     if (!(k->is_instance_klass() && InstanceKlass::cast(k)->is_in_error_state())) {
       _global_klass_objects->append_if_missing(k);
     }
+    if (k->is_array_klass()) {
+      // Add in the array classes too
+      ArrayKlass* ak = ArrayKlass::cast(k);
+      Klass* h = ak->higher_dimension();
+      if (h != NULL) {
+        h->array_klasses_do(collect_array_classes);
+      }
+    }
   }
 };
 
 static void remove_unshareable_in_classes() {
   for (int i = 0; i < _global_klass_objects->length(); i++) {
     Klass* k = _global_klass_objects->at(i);
-    k->remove_unshareable_info();
+    if (!k->is_objArray_klass()) {
+      // InstanceKlass and TypeArrayKlass will in turn call remove_unshareable_info
+      // on their array classes.
+      assert(k->is_instance_klass() || k->is_typeArray_klass(), "must be");
+      k->remove_unshareable_info();
+    }
+  }
+}
+
+static void remove_java_mirror_in_classes() {
+  for (int i = 0; i < _global_klass_objects->length(); i++) {
+    Klass* k = _global_klass_objects->at(i);
+    if (!k->is_objArray_klass()) {
+      // InstanceKlass and TypeArrayKlass will in turn call remove_unshareable_info
+      // on their array classes.
+      assert(k->is_instance_klass() || k->is_typeArray_klass(), "must be");
+      k->remove_java_mirror();
+    }
   }
 }
 
 static void rewrite_nofast_bytecode(Method* method) {
-  RawBytecodeStream bcs(method);
+  BytecodeStream bcs(method);
   while (!bcs.is_last_bytecode()) {
-    Bytecodes::Code opcode = bcs.raw_next();
+    Bytecodes::Code opcode = bcs.next();
     switch (opcode) {
     case Bytecodes::_getfield:      *bcs.bcp() = Bytecodes::_nofast_getfield;      break;
     case Bytecodes::_putfield:      *bcs.bcp() = Bytecodes::_nofast_putfield;      break;
@@ -446,6 +484,17 @@
   }
 }
 
+NOT_PRODUCT(
+static void assert_not_anonymous_class(InstanceKlass* k) {
+  assert(!(k->is_anonymous()), "cannot archive anonymous classes");
+}
+
+// Anonymous classes are not stored inside any dictionaries. They are created by
+// SystemDictionary::parse_stream() with a non-null host_klass.
+static void assert_no_anonymoys_classes_in_dictionaries() {
+  ClassLoaderDataGraph::dictionary_classes_do(assert_not_anonymous_class);
+})
+
 // Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables.
 // (In GCC this is the field <Type>::_vptr, i.e., first word in the object.)
 //
@@ -957,8 +1006,8 @@
     }
     memcpy(p, obj, bytes);
     bool isnew = _new_loc_table->put(obj, (address)p);
+    log_trace(cds)("Copy: " PTR_FORMAT " ==> " PTR_FORMAT " %d", p2i(obj), p2i(p), bytes);
     assert(isnew, "must be");
-    log_trace(cds)("Copy: " PTR_FORMAT " ==> " PTR_FORMAT " %d", p2i(obj), p2i(p), bytes);
 
     _alloc_stats->record(ref->msotype(), int(newtop - oldtop), read_only);
     if (ref->msotype() == MetaspaceObj::SymbolType) {
@@ -1151,6 +1200,9 @@
   // Reorder the system dictionary. Moving the symbols affects
   // how the hash table indices are calculated.
   SystemDictionary::reorder_dictionary_for_sharing();
+  tty->print("Removing java_mirror ... ");
+  remove_java_mirror_in_classes();
+  tty->print_cr("done. ");
   NOT_PRODUCT(SystemDictionary::verify();)
 
   size_t buckets_bytes = SystemDictionary::count_bytes_for_buckets();
@@ -1218,11 +1270,20 @@
   rewrite_nofast_bytecodes_and_calculate_fingerprints();
   tty->print_cr("done. ");
 
+  // Move classes from platform/system dictionaries into the boot dictionary
+  SystemDictionary::combine_shared_dictionaries();
+
   // Remove all references outside the metadata
   tty->print("Removing unshareable information ... ");
   remove_unshareable_in_classes();
   tty->print_cr("done. ");
 
+  // We don't support archiving anonymous classes. Verify that they are not stored in
+  // the any dictionaries.
+  NOT_PRODUCT(assert_no_anonymoys_classes_in_dictionaries());
+
+  SystemDictionaryShared::finalize_verification_constraints();
+
   ArchiveCompactor::initialize();
   ArchiveCompactor::copy_and_compact();
 
@@ -1312,6 +1373,14 @@
     ArchiveCompactor::alloc_stats()->print_stats(int(_ro_region.used()), int(_rw_region.used()),
                                                  int(_mc_region.used()), int(_md_region.used()));
   }
+
+  if (PrintSystemDictionaryAtExit) {
+    SystemDictionary::print();
+  }
+  // There may be other pending VM operations that operate on the InstanceKlasses,
+  // which will fail because InstanceKlasses::remove_unshareable_info()
+  // has been called. Forget these operations and exit the VM directly.
+  vm_direct_exit(0);
 }
 
 void VM_PopulateDumpSharedSpace::print_region_stats() {
@@ -1438,10 +1507,6 @@
       exit(1);
     }
   }
-
-  // Copy the verification constraints from C_HEAP-alloced GrowableArrays to RO-alloced
-  // Arrays
-  SystemDictionaryShared::finalize_verification_constraints();
 }
 
 void MetaspaceShared::prepare_for_dumping() {
@@ -1509,17 +1574,11 @@
     link_and_cleanup_shared_classes(CATCH);
     tty->print_cr("Rewriting and linking classes: done");
 
+    SystemDictionary::clear_invoke_method_table();
+
     VM_PopulateDumpSharedSpace op;
     VMThread::execute(&op);
   }
-
-  if (PrintSystemDictionaryAtExit) {
-    SystemDictionary::print();
-  }
-
-  // Since various initialization steps have been undone by this process,
-  // it is not reasonable to continue running a java process.
-  exit(0);
 }
 
 
@@ -1529,8 +1588,14 @@
 
     while (parser.parse_one_line()) {
       Klass* klass = ClassLoaderExt::load_one_class(&parser, THREAD);
-
-      CLEAR_PENDING_EXCEPTION;
+      if (HAS_PENDING_EXCEPTION) {
+        if (klass == NULL &&
+             (PENDING_EXCEPTION->klass()->name() == vmSymbols::java_lang_ClassNotFoundException())) {
+          // print a warning only when the pending exception is class not found
+          tty->print_cr("Preload Warning: Cannot find %s", parser.current_class_name());
+        }
+        CLEAR_PENDING_EXCEPTION;
+      }
       if (klass != NULL) {
         if (log_is_enabled(Trace, cds)) {
           ResourceMark rm;