src/hotspot/share/classfile/classLoaderExt.hpp
changeset 48138 78b2ecdd3c4b
parent 47991 a474466c4fdb
child 49341 4ad0085ad6d2
--- a/src/hotspot/share/classfile/classLoaderExt.hpp	Mon Nov 27 20:35:56 2017 -0500
+++ b/src/hotspot/share/classfile/classLoaderExt.hpp	Mon Nov 27 20:21:34 2017 -0800
@@ -26,65 +26,152 @@
 #define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
 
 #include "classfile/classLoader.hpp"
-#include "classfile/systemDictionary.hpp"
-#include "oops/instanceKlass.hpp"
-#include "runtime/handles.hpp"
+#include "utilities/macros.hpp"
 
-class ClassListParser;
+CDS_ONLY(class SharedPathsMiscInfoExt;)
+CDS_ONLY(class ClassListParser;)
 
 class ClassLoaderExt: public ClassLoader { // AllStatic
 public:
-
+  enum SomeConstants {
+    max_classpath_index = 0x7fff
+  };
+  // ClassLoaderExt::Context --
+  //
+  // This is used by DumpSharedSpaces only - it enforces the same classloader
+  // delegation model as would be in run-time. I.e.,
+  // + classes defined by the NULL class loader cannot load classes in the PLATFORM or APP paths.
+  // + classes defined by the PLATFORM class loader cannot load classes in the APP paths.
   class Context {
+    static Thread* _dump_thread;
+    const char* _class_name;
     const char* _file_name;
   public:
+    const char* class_name() {
+      return _class_name;
+    }
+    const char* file_name() {
+      return _file_name;
+    }
+
     Context(const char* class_name, const char* file_name, TRAPS) {
+      _class_name = class_name;
       _file_name = file_name;
+#if INCLUDE_CDS
+      if (!DumpSharedSpaces && !UseSharedSpaces) {
+        // Must not modify _app_paths_start_index if we're not using CDS.
+        assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
+      }
+#endif
     }
 
     bool check(const ClassFileStream* stream, const int classpath_index) {
-      return true;
+      CDS_ONLY(return ClassLoaderExt::check(this, stream, classpath_index);)
+      NOT_CDS(return true;)
     }
 
     bool should_verify(int classpath_index) {
-      return false;
+      CDS_ONLY(return (classpath_index >= _app_paths_start_index);)
+      NOT_CDS(return false;)
     }
 
     void record_result(Symbol* class_name,
                        const s2 classpath_index,
-                       InstanceKlass* result, TRAPS) {
+                       InstanceKlass* result,
+                       TRAPS) {
 #if INCLUDE_CDS
-      assert(DumpSharedSpaces, "Sanity");
-      oop loader = result->class_loader();
-      s2 classloader_type = ClassLoader::BOOT_LOADER;
-      if (SystemDictionary::is_system_class_loader(loader)) {
-        classloader_type = ClassLoader::APP_LOADER;
-        ClassLoaderExt::set_has_app_classes();
-      } else if (SystemDictionary::is_platform_class_loader(loader)) {
-        classloader_type = ClassLoader::PLATFORM_LOADER;
-        ClassLoaderExt::set_has_platform_classes();
+      ClassLoaderExt::record_result(this, class_name, classpath_index, result, THREAD);
+#endif
+    }
+
+    ~Context() {
+#if INCLUDE_CDS
+      if (!DumpSharedSpaces && !UseSharedSpaces) {
+        // Must not modify app_paths_start_index if we're not using CDS.
+        assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
       }
-      result->set_shared_classpath_index(classpath_index);
-      result->set_class_loader_type(classloader_type);
 #endif
     }
-  };
+  }; // end ClassLoaderExt::Context
 
+private:
+#if INCLUDE_CDS
+  static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size);
+  static void setup_app_search_path(); // Only when -Xshare:dump
+  static SharedPathsMiscInfoExt* shared_paths_misc_info() {
+    return (SharedPathsMiscInfoExt*)_shared_paths_misc_info;
+  }
+  static jshort _app_paths_start_index; // index of first app JAR in shared classpath entry table
+  static bool _has_app_classes;
+  static bool _has_platform_classes;
+#endif
+
+public:
+  CDS_ONLY(static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates);)
+
+  // Called by JVMTI code to add boot classpath
   static void append_boot_classpath(ClassPathEntry* new_entry) {
+#if INCLUDE_CDS
+    if (UseAppCDS) {
+      warning("UseAppCDS is disabled because bootstrap classpath has been appended");
+      UseAppCDS = false;
+    }
+#endif
     ClassLoader::add_to_boot_append_entries(new_entry);
   }
-  static void setup_search_paths() {}
-  static bool is_boot_classpath(int classpath_index) {
-   return true;
- }
-  static Klass* load_one_class(ClassListParser* parser, TRAPS);
+
+  static void setup_search_paths() NOT_CDS_RETURN;
+
 #if INCLUDE_CDS
-  static void set_has_app_classes() {}
-  static void set_has_platform_classes() {}
+private:
+  static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS);
+  static ClassPathEntry* find_classpath_entry_from_cache(const char* path, TRAPS);
+
+public:
   static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) {
-    return NULL;
+    // Remove all the new-line continuations (which wrap long lines at 72 characters, see
+    // http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest), so
+    // that the manifest is easier to parse.
+    return read_manifest(entry, manifest_size, true, THREAD);
+  }
+  static char* read_raw_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) {
+    // Do not remove new-line continuations, so we can easily pass it as an argument to
+    // java.util.jar.Manifest.getManifest() at run-time.
+    return read_manifest(entry, manifest_size, false, THREAD);
+  }
+
+  static void finalize_shared_paths_misc_info();
+
+  static jshort app_paths_start_index() { return _app_paths_start_index; }
+
+  static void init_paths_start_index(jshort app_start) {
+    _app_paths_start_index = app_start;
+  }
+
+  static bool is_boot_classpath(int classpath_index) {
+    return classpath_index < _app_paths_start_index;
   }
-  static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates) {}
+
+  static bool has_platform_or_app_classes() {
+    return _has_app_classes || _has_platform_classes;
+  }
+
+  static bool check(class ClassLoaderExt::Context *context,
+                    const ClassFileStream* stream,
+                    const int classpath_index);
+
+  static void record_result(class ClassLoaderExt::Context *context,
+                            Symbol* class_name,
+                            const s2 classpath_index,
+                            InstanceKlass* result, TRAPS);
+  static InstanceKlass* load_class(Symbol* h_name, const char* path, TRAPS);
+  static Klass* load_one_class(ClassListParser* parser, TRAPS);
+  static void set_has_app_classes() {
+    _has_app_classes = true;
+  }
+  static void set_has_platform_classes() {
+    _has_platform_classes = true;
+  }
 #endif
 };