hotspot/src/share/vm/classfile/classLoader.cpp
changeset 47103 a993ec29ec75
parent 47089 27050b653624
child 47106 bed18a111b90
--- a/hotspot/src/share/vm/classfile/classLoader.cpp	Wed Aug 30 19:18:22 2017 -0400
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Mon Aug 28 15:34:04 2017 -0700
@@ -147,6 +147,7 @@
 ClassPathEntry* ClassLoader::_first_append_entry = NULL;
 ClassPathEntry* ClassLoader::_last_append_entry  = NULL;
 int             ClassLoader::_num_entries        = 0;
+int             ClassLoader::_num_boot_entries   = -1;
 #if INCLUDE_CDS
 GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
 GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
@@ -242,7 +243,7 @@
 
 // Given a fully qualified class name, find its defining package in the class loader's
 // package entry table.
-static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
+PackageEntry* ClassLoader::get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
   ResourceMark rm(THREAD);
   const char *pkg_name = ClassLoader::package_from_name(class_name);
   if (pkg_name == NULL) {
@@ -509,7 +510,7 @@
 #endif
 
       } else {
-        PackageEntry* package_entry = get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), CHECK_NULL);
+        PackageEntry* package_entry = ClassLoader::get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), CHECK_NULL);
         if (package_entry != NULL) {
           ResourceMark rm;
           // Get the module name
@@ -540,6 +541,13 @@
   return NULL;
 }
 
+JImageLocationRef ClassLoader::jimage_find_resource(JImageFile* jf,
+                                                    const char* module_name,
+                                                    const char* file_name,
+                                                    jlong &size) {
+  return ((*JImageFindResource)(jf, module_name, get_jimage_version_string(), file_name, &size));
+}
+
 #ifndef PRODUCT
 bool ctw_visitor(JImageFile* jimage,
         const char* module_name, const char* version, const char* package,
@@ -1459,9 +1467,6 @@
   // This would include:
   //   [--patch-module=<module>=<file>(<pathsep><file>)*]; [jimage | exploded module build]
   //
-  // DumpSharedSpaces and search_append_only are mutually exclusive and cannot
-  // be true at the same time.
-  assert(!(DumpSharedSpaces && search_append_only), "DumpSharedSpaces and search_append_only are both true");
 
   // Load Attempt #1: --patch-module
   // Determine the class' defining module.  If it appears in the _patch_mod_entries,
@@ -1507,6 +1512,11 @@
 
     e = _first_append_entry;
     while (e != NULL) {
+      if (DumpSharedSpaces && classpath_index >= _num_boot_entries) {
+        // Do not load any class from the app classpath using the boot loader. Let
+        // the built-in app class laoder load them.
+        break;
+      }
       stream = e->open_stream(file_name, CHECK_NULL);
       if (!context.check(stream, classpath_index)) {
         return NULL;
@@ -1520,9 +1530,6 @@
   }
 
   if (NULL == stream) {
-    if (DumpSharedSpaces) {
-      tty->print_cr("Preload Warning: Cannot find %s", class_name);
-    }
     return NULL;
   }
 
@@ -1548,6 +1555,100 @@
   return context.record_result(name, e, classpath_index, result, THREAD);
 }
 
+#if INCLUDE_CDS
+static char* 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
+    int offset = 5;
+    while (*(source + offset) == '/') {
+        offset++;
+    }
+    source += offset;
+  // for non-windows platforms, move back one char as the path begins with a '/'
+#ifndef _WINDOWS
+    source -= 1;
+#endif
+  } else if (strncmp(source, "jrt:/", 5) == 0) {
+    source += 5;
+  }
+  return source;
+}
+
+void ClassLoader::record_shared_class_loader_type(InstanceKlass* ik, const ClassFileStream* stream) {
+  assert(DumpSharedSpaces, "sanity");
+  assert(stream != NULL, "sanity");
+
+  if (ik->is_anonymous()) {
+    // We do not archive anonymous classes.
+    return;
+  }
+
+  if (stream->source() == NULL) {
+    if (ik->class_loader() == NULL) {
+      // JFR classes
+      ik->set_shared_classpath_index(0);
+      ik->set_class_loader_type(ClassLoader::BOOT_LOADER);
+    }
+    return;
+  }
+
+  assert(has_jrt_entry(), "CDS dumping does not support exploded JDK build");
+
+  ModuleEntry* module = ik->module();
+  ClassPathEntry* e = NULL;
+  int classpath_index = 0;
+
+  // Check if the class is from the runtime image
+  if (module != NULL && (module->location() != NULL) &&
+      (module->location()->starts_with("jrt:"))) {
+    e = _jrt_entry;
+    classpath_index = 0;
+  } else {
+    classpath_index = 1;
+    ResourceMark rm;
+    char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
+    for (e = _first_append_entry; e != NULL; e = e->next()) {
+      if (get_canonical_path(e->name(), canonical_path, JVM_MAXPATHLEN)) {
+        char* src = (char*)stream->source();
+        // save the path from the file: protocol or the module name from the jrt: protocol
+        // if no protocol prefix is found, src is the same as stream->source() after the following call
+        src = skip_uri_protocol(src);
+        if (strcmp(canonical_path, os::native_path((char*)src)) == 0) {
+          break;
+        }
+        classpath_index ++;
+      }
+    }
+    if (e == NULL) {
+      assert(ik->shared_classpath_index() < 0,
+        "must be a class from a custom jar which isn't in the class path or boot class path");
+      return;
+    }
+  }
+
+  if (classpath_index < _num_boot_entries) {
+    // ik is either:
+    // 1) a boot class loaded from the runtime image during vm initialization (classpath_index = 0); or
+    // 2) a user's class from -Xbootclasspath/a (classpath_index > 0)
+    // In the second case, the classpath_index, classloader_type will be recorded via
+    // context.record_result() in ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS).
+    if (classpath_index > 0) {
+      return;
+    }
+  }
+
+  ResourceMark rm;
+  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(), e, classpath_index, ik, THREAD);
+}
+#endif // INCLUDE_CDS
+
 // Initialize the class loader's access to methods in libzip.  Parse and
 // process the boot classpath into a list ClassPathEntry objects.  Once
 // this list has been created, it must not change order (see class PackageInfo)
@@ -1632,6 +1733,7 @@
 #if INCLUDE_CDS
 void ClassLoader::initialize_shared_path() {
   if (DumpSharedSpaces) {
+    _num_boot_entries = _num_entries;
     ClassLoaderExt::setup_search_paths();
     _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
   }