src/hotspot/share/classfile/classLoader.cpp
changeset 49739 00805b129186
parent 49612 f40a666a75bc
child 49747 376792a6e9da
--- a/src/hotspot/share/classfile/classLoader.cpp	Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/classLoader.cpp	Tue Apr 10 11:43:40 2018 -0700
@@ -148,6 +148,8 @@
 #if INCLUDE_CDS
 ClassPathEntry* ClassLoader::_app_classpath_entries = NULL;
 ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
+ClassPathEntry* ClassLoader::_module_path_entries = NULL;
+ClassPathEntry* ClassLoader::_last_module_path_entry = NULL;
 SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
 #endif
 
@@ -721,7 +723,44 @@
   }
 }
 
-#endif
+void ClassLoader::add_to_module_path_entries(const char* path,
+                                             ClassPathEntry* entry) {
+  assert(entry != NULL, "ClassPathEntry should not be NULL");
+  assert(DumpSharedSpaces, "dump time only");
+
+  // The entry does not exist, add to the list
+  if (_module_path_entries == NULL) {
+    assert(_last_module_path_entry == NULL, "Sanity");
+    _module_path_entries = _last_module_path_entry = entry;
+  } else {
+    _last_module_path_entry->set_next(entry);
+    _last_module_path_entry = entry;
+  }
+}
+
+// Add a module path to the _module_path_entries list.
+void ClassLoader::update_module_path_entry_list(const char *path, TRAPS) {
+  assert(DumpSharedSpaces, "dump time only");
+  struct stat st;
+  int ret = os::stat(path, &st);
+  assert(ret == 0, "module path must exist");
+  // File or directory found
+  ClassPathEntry* new_entry = NULL;
+  new_entry = create_class_path_entry(path, &st, true /* throw_exception */,
+                                      false /*is_boot_append */, CHECK);
+  if (new_entry == NULL) {
+    return;
+  }
+
+  add_to_module_path_entries(path, new_entry);
+  return;
+}
+
+void ClassLoader::setup_module_search_path(const char* path, TRAPS) {
+  check_shared_classpath(path);
+  update_module_path_entry_list(path, THREAD);
+}
+#endif // INCLUDE_CDS
 
 // Construct the array of module/path pairs as specified to --patch-module
 // for the boot loader to search ahead of the jimage, if the class being
@@ -1512,7 +1551,7 @@
 }
 
 #if INCLUDE_CDS
-static char* skip_uri_protocol(char* source) {
+char* ClassLoader::skip_uri_protocol(char* source) {
   if (strncmp(source, "file:", 5) == 0) {
     // file: protocol path could start with file:/ or file:///
     // locate the char after all the forward slashes
@@ -1533,7 +1572,7 @@
 
 // Record the shared classpath index and loader type for classes loaded
 // by the builtin loaders at dump time.
-void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream) {
+void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS) {
   assert(DumpSharedSpaces, "sanity");
   assert(stream != NULL, "sanity");
 
@@ -1542,9 +1581,10 @@
     return;
   }
 
+  oop loader = ik->class_loader();
   char* src = (char*)stream->source();
   if (src == NULL) {
-    if (ik->class_loader() == NULL) {
+    if (loader == NULL) {
       // JFR classes
       ik->set_shared_classpath_index(0);
       ik->set_class_loader_type(ClassLoader::BOOT_LOADER);
@@ -1554,41 +1594,84 @@
 
   assert(has_jrt_entry(), "CDS dumping does not support exploded JDK build");
 
-  ModuleEntry* module = ik->module();
+  ResourceMark rm(THREAD);
   int classpath_index = -1;
-  ResourceMark rm;
-  char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
+  PackageEntry* pkg_entry = ik->package();
+
+  if (FileMapInfo::get_number_of_shared_paths() > 0) {
+    char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
 
-  // save the path from the file: protocol or the module name from the jrt: protocol
-  // if no protocol prefix is found, path is the same as stream->source()
-  char* path = skip_uri_protocol(src);
-  for (int i = 0; i < FileMapInfo::get_number_of_share_classpaths(); i++) {
-    SharedClassPathEntry* ent = FileMapInfo::shared_classpath(i);
-    if (get_canonical_path(ent->name(), canonical_path, JVM_MAXPATHLEN)) {
-      // If the path (from the class stream srouce) is the same as the shared
-      // class path, then we have a match. For classes from module image loaded by the
-      // PlatformClassLoader, the stream->source() is not the name of the module image.
-      // Need to look for 'jrt:' explicitly.
-      if (strcmp(canonical_path, os::native_path((char*)path)) == 0 ||
-          (i == 0 && string_starts_with(src, "jrt:"))) {
-        classpath_index = i;
-        break;
+    // save the path from the file: protocol or the module name from the jrt: protocol
+    // if no protocol prefix is found, path is the same as stream->source()
+    char* path = skip_uri_protocol(src);
+    for (int i = 0; i < FileMapInfo::get_number_of_shared_paths(); i++) {
+      SharedClassPathEntry* ent = FileMapInfo::shared_path(i);
+      if (get_canonical_path(ent->name(), canonical_path, JVM_MAXPATHLEN)) {
+        // If the path (from the class stream source) is the same as the shared
+        // class or module path, then we have a match.
+        if (strcmp(canonical_path, os::native_path((char*)path)) == 0) {
+          // NULL pkg_entry and pkg_entry in an unnamed module implies the class
+          // is from the -cp or boot loader append path which consists of -Xbootclasspath/a
+          // and jvmti appended entries.
+          if ((pkg_entry == NULL) || (pkg_entry->in_unnamed_module())) {
+            // Ensure the index is within the -cp range before assigning
+            // to the classpath_index.
+            if (SystemDictionary::is_system_class_loader(loader) &&
+                (i >= ClassLoaderExt::app_class_paths_start_index()) &&
+                (i < ClassLoaderExt::app_module_paths_start_index())) {
+              classpath_index = i;
+              break;
+            } else {
+              if ((i >= 1) &&
+                  (i < ClassLoaderExt::app_class_paths_start_index())) {
+                // The class must be from boot loader append path which consists of
+                // -Xbootclasspath/a and jvmti appended entries.
+                assert(loader == NULL, "sanity");
+                classpath_index = i;
+                break;
+              }
+            }
+          } else {
+            // A class from a named module from the --module-path. Ensure the index is
+            // within the --module-path range before assigning to the classpath_index.
+            if ((pkg_entry != NULL) && !(pkg_entry->in_unnamed_module()) && (i > 0)) {
+              if (i >= ClassLoaderExt::app_module_paths_start_index() &&
+                  i < FileMapInfo::get_number_of_shared_paths()) {
+                classpath_index = i;
+                break;
+              }
+            }
+          }
+        }
+        // for index 0 and the stream->source() is the modules image or has the jrt: protocol.
+        // The class must be from the runtime modules image.
+        if (i == 0 && (is_modules_image(src) || string_starts_with(src, "jrt:"))) {
+          classpath_index = i;
+          break;
+        }
       }
     }
-  }
-  if (classpath_index < 0) {
-    // Shared classpath entry table only contains boot class path and -cp path.
+
     // No path entry found for this class. Must be a shared class loaded by the
     // user defined classloader.
-    assert(ik->shared_classpath_index() < 0, "Sanity");
-    return;
+    if (classpath_index < 0) {
+      assert(ik->shared_classpath_index() < 0, "Sanity");
+      return;
+    }
+  } else {
+    // The shared path table is set up after module system initialization.
+    // The path table contains no entry before that. Any classes loaded prior
+    // to the setup of the shared path table must be from the modules image.
+    assert(is_modules_image(src), "stream must be from modules image");
+    assert(FileMapInfo::get_number_of_shared_paths() == 0, "shared path table must not have been setup");
+    classpath_index = 0;
   }
 
   const char* const class_name = ik->name()->as_C_string();
   const char* const file_name = file_name_for_class_name(class_name,
                                                          ik->name()->utf8_length());
   assert(file_name != NULL, "invariant");
-  Thread* THREAD = Thread::current();
+
   ClassLoaderExt::Context context(class_name, file_name, CATCH);
   context.record_result(ik->name(), classpath_index, ik, THREAD);
 }
@@ -1673,6 +1756,13 @@
     _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
   }
 }
+
+void ClassLoader::initialize_module_path(TRAPS) {
+  if (DumpSharedSpaces) {
+    ClassLoaderExt::setup_module_paths(THREAD);
+    FileMapInfo::allocate_shared_path_table();
+  }
+}
 #endif
 
 jlong ClassLoader::classloader_time_ms() {