hotspot/src/share/vm/classfile/systemDictionary.cpp
changeset 47103 a993ec29ec75
parent 47098 e704f55561c3
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Aug 30 19:18:22 2017 -0400
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Mon Aug 28 15:34:04 2017 -0700
@@ -66,6 +66,7 @@
 #include "prims/resolvedMethodTable.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/arguments_ext.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/fieldType.hpp"
 #include "runtime/handles.inline.hpp"
@@ -869,7 +870,7 @@
             // during compilations.
             MutexLocker mu(Compile_lock, THREAD);
             update_dictionary(d_index, d_hash, p_index, p_hash,
-                              k, class_loader, THREAD);
+              k, class_loader, THREAD);
           }
 
           if (JvmtiExport::should_post_class_load()) {
@@ -1006,7 +1007,6 @@
     // Create a new CLD for anonymous class, that uses the same class loader
     // as the host_klass
     guarantee(host_klass->class_loader() == class_loader(), "should be the same");
-    guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping");
     loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
   } else {
     loader_data = ClassLoaderData::class_loader_data(class_loader());
@@ -1075,6 +1075,15 @@
                                                      Handle protection_domain,
                                                      ClassFileStream* st,
                                                      TRAPS) {
+#if INCLUDE_CDS
+  ResourceMark rm(THREAD);
+  if (DumpSharedSpaces && !class_loader.is_null() &&
+      !ArgumentsExt::using_AppCDS() && strcmp(class_name->as_C_string(), "Unnamed") != 0) {
+    // If AppCDS is not enabled, don't define the class at dump time (except for the "Unnamed"
+    // class, which is used by MethodHandles).
+    THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string());
+  }
+#endif
 
   HandleMark hm(THREAD);
 
@@ -1101,11 +1110,13 @@
  InstanceKlass* k = NULL;
 
 #if INCLUDE_CDS
-  k = SystemDictionaryShared::lookup_from_stream(class_name,
-                                                 class_loader,
-                                                 protection_domain,
-                                                 st,
-                                                 CHECK_NULL);
+  if (!DumpSharedSpaces) {
+    k = SystemDictionaryShared::lookup_from_stream(class_name,
+                                                   class_loader,
+                                                   protection_domain,
+                                                   st,
+                                                   CHECK_NULL);
+  }
 #endif
 
   if (k == NULL) {
@@ -1214,6 +1225,16 @@
          "Cannot use sharing if java.base is patched");
   ResourceMark rm;
   int path_index = ik->shared_classpath_index();
+  ClassLoaderData* loader_data = class_loader_data(class_loader);
+  if (path_index < 0) {
+    // path_index < 0 indicates that the class is intended for a custom loader
+    // and should not be loaded by boot/platform/app loaders
+    if (loader_data->is_builtin_class_loader_data()) {
+      return false;
+    } else {
+      return true;
+    }
+  }
   SharedClassPathEntry* ent =
             (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
   if (!Universe::is_module_initialized()) {
@@ -1227,7 +1248,6 @@
   PackageEntry* pkg_entry = NULL;
   ModuleEntry* mod_entry = NULL;
   const char* pkg_string = NULL;
-  ClassLoaderData* loader_data = class_loader_data(class_loader);
   pkg_name = InstanceKlass::package_from_name(class_name, CHECK_false);
   if (pkg_name != NULL) {
     pkg_string = pkg_name->as_C_string();
@@ -1400,6 +1420,18 @@
   }
   return ik;
 }
+
+void SystemDictionary::clear_invoke_method_table() {
+  SymbolPropertyEntry* spe = NULL;
+  for (int index = 0; index < _invoke_method_table->table_size(); index++) {
+    SymbolPropertyEntry* p = _invoke_method_table->bucket(index);
+    while (p != NULL) {
+      spe = p;
+      p = p->next();
+      _invoke_method_table->free_entry(spe);
+    }
+  }
+}
 #endif // INCLUDE_CDS
 
 InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
@@ -1446,7 +1478,6 @@
         }
       }
     } else {
-      assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
       // After the module system has been initialized, check if the class'
       // package is in a module defined to the boot loader.
       if (pkg_name == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
@@ -1965,8 +1996,19 @@
   invoke_method_table()->methods_do(f);
 }
 
+class RemoveClassesClosure : public CLDClosure {
+  public:
+    void do_cld(ClassLoaderData* cld) {
+      if (cld->is_system_class_loader_data() || cld->is_platform_class_loader_data()) {
+        cld->dictionary()->remove_classes_in_error_state();
+      }
+    }
+};
+
 void SystemDictionary::remove_classes_in_error_state() {
   ClassLoaderData::the_null_class_loader_data()->dictionary()->remove_classes_in_error_state();
+  RemoveClassesClosure rcc;
+  ClassLoaderDataGraph::cld_do(&rcc);
 }
 
 // ----------------------------------------------------------------------------
@@ -2907,6 +2949,56 @@
   }
 }
 
+class CombineDictionariesClosure : public CLDClosure {
+  private:
+    Dictionary* _master_dictionary;
+  public:
+    CombineDictionariesClosure(Dictionary* master_dictionary) :
+      _master_dictionary(master_dictionary) {}
+    void do_cld(ClassLoaderData* cld) {
+      ResourceMark rm;
+      if (cld->is_system_class_loader_data() || cld->is_platform_class_loader_data()) {
+        for (int i = 0; i < cld->dictionary()->table_size(); ++i) {
+          Dictionary* curr_dictionary = cld->dictionary();
+          DictionaryEntry* p = curr_dictionary->bucket(i);
+          while (p != NULL) {
+            Symbol* name = p->instance_klass()->name();
+            unsigned int d_hash = _master_dictionary->compute_hash(name);
+            int d_index = _master_dictionary->hash_to_index(d_hash);
+            DictionaryEntry* next = p->next();
+            if (p->literal()->class_loader_data() != cld) {
+              // This is an initiating class loader entry; don't use it
+              log_trace(cds)("Skipping initiating cl entry: %s", name->as_C_string());
+              curr_dictionary->free_entry(p);
+            } else {
+              log_trace(cds)("Moved to boot dictionary: %s", name->as_C_string());
+              curr_dictionary->unlink_entry(p);
+              p->set_pd_set(NULL); // pd_set is runtime only information and will be reconstructed.
+              _master_dictionary->add_entry(d_index, p);
+            }
+            p = next;
+          }
+          *curr_dictionary->bucket_addr(i) = NULL;
+        }
+      }
+    }
+};
+
+// Combining platform and system loader dictionaries into boot loader dictionaries.
+// During run time, we only have one shared dictionary.
+void SystemDictionary::combine_shared_dictionaries() {
+  assert(DumpSharedSpaces, "dump time only");
+  Dictionary* master_dictionary = ClassLoaderData::the_null_class_loader_data()->dictionary();
+  CombineDictionariesClosure cdc(master_dictionary);
+  ClassLoaderDataGraph::cld_do(&cdc);
+
+  // These tables are no longer valid or necessary. Keeping them around will
+  // cause SystemDictionary::verify() to fail. Let's empty them.
+  _placeholders        = new PlaceholderTable(_placeholder_table_size);
+  _loader_constraints  = new LoaderConstraintTable(_loader_constraint_size);
+
+  NOT_PRODUCT(SystemDictionary::verify());
+}
 
 // caller needs ResourceMark
 const char* SystemDictionary::loader_name(const oop loader) {