< prev index next >

src/hotspot/share/memory/filemap.cpp

Print this page

@@ -23,12 +23,12 @@
  */
 
 #include "precompiled.hpp"
 #include "jvm.h"
 #include "classfile/classLoader.inline.hpp"
+#include "classfile/classLoaderExt.hpp"
 #include "classfile/compactHashtable.inline.hpp"
-#include "classfile/sharedClassUtil.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "classfile/altHashing.hpp"
 #include "logging/log.hpp"

@@ -157,12 +157,13 @@
   assert(_current_info == NULL, "must be singleton"); // not thread safe
   _current_info = this;
   memset((void*)this, 0, sizeof(FileMapInfo));
   _file_offset = 0;
   _file_open = false;
-  _header = SharedClassUtil::allocate_file_map_header();
+  _header = new FileMapHeader();
   _header->_version = _invalid_version;
+  _header->_has_platform_or_app_classes = true; 
 }
 
 FileMapInfo::~FileMapInfo() {
   assert(_current_info == this, "must be singleton"); // not thread safe
   _current_info = NULL;

@@ -171,11 +172,11 @@
 void FileMapInfo::populate_header(size_t alignment) {
   _header->populate(this, alignment);
 }
 
 size_t FileMapInfo::FileMapHeader::data_size() {
-  return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase);
+  return sizeof(FileMapHeader) - sizeof(FileMapInfo::FileMapHeaderBase);
 }
 
 void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
   _magic = 0xf00baba2;
   _version = _current_version;

@@ -196,10 +197,18 @@
   // will function correctly with this JVM and the bootclasspath it's
   // invoked with.
 
   // JVM version string ... changes on each build.
   get_header_version(_jvm_ident);
+
+  ClassLoaderExt::finalize_shared_paths_misc_info();
+  _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
+  _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
+
+  _verify_local = BytecodeVerificationLocal;
+  _verify_remote = BytecodeVerificationRemote;
+  _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
 }
 
 void SharedClassPathEntry::init(const char* name, TRAPS) {
   _timestamp = 0;
   _filesize  = 0;

@@ -276,11 +285,11 @@
   ClassPathEntry* jrt = ClassLoader::get_jrt_entry();
 
   assert(jrt != NULL,
          "No modular java runtime image present when allocating the CDS classpath entry table");
 
-  size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??)
+  size_t entry_size = sizeof(SharedClassPathEntry); // assert ( should be 8 byte aligned??)
   int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries();
   int num_app_classpath_entries = ClassLoader::num_app_classpath_entries();
   int num_module_path_entries = ClassLoader::num_module_path_entries();
   int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries;
   size_t bytes = entry_size * num_entries;

@@ -297,11 +306,11 @@
     log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
     SharedClassPathEntry* ent = shared_path(i);
     ent->init(cpe->name(), THREAD);
     if (cpe != jrt) { // No need to do jimage.
       EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
-      SharedClassUtil::update_shared_classpath(cpe, ent, THREAD);
+      update_shared_classpath(cpe, ent, THREAD);
     }
     cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
     i++;
   }
   assert(i == num_boot_classpath_entries,

@@ -312,11 +321,11 @@
   while (acpe != NULL) {
     log_info(class, path)("add app shared path %s", acpe->name());
     SharedClassPathEntry* ent = shared_path(i);
     ent->init(acpe->name(), THREAD);
     EXCEPTION_MARK;
-    SharedClassUtil::update_shared_classpath(acpe, ent, THREAD);
+    update_shared_classpath(acpe, ent, THREAD);
     acpe = acpe->next();
     i++;
   }
 
   // 3. module path

@@ -324,11 +333,11 @@
   while (mpe != NULL) {
     log_info(class, path)("add module path %s",mpe->name());
     SharedClassPathEntry* ent = shared_path(i);
     ent->init(mpe->name(), THREAD);
     EXCEPTION_MARK;
-    SharedClassUtil::update_shared_classpath(mpe, ent, THREAD);
+    update_shared_classpath(mpe, ent, THREAD);
     mpe = mpe->next();
     i++;
   }
   assert(i == num_entries, "number of shared path entry mismatch");
 }

@@ -358,26 +367,103 @@
   if (has_nonempty_dir) {
     ClassLoader::exit_with_path_failure("Cannot have non-empty directory in paths", NULL);
   }
 }
 
+class ManifestStream: public ResourceObj {
+  private:
+  u1*   _buffer_start; // Buffer bottom
+  u1*   _buffer_end;   // Buffer top (one past last element)
+  u1*   _current;      // Current buffer position
+
+ public:
+  // Constructor
+  ManifestStream(u1* buffer, int length) : _buffer_start(buffer),
+                                           _current(buffer) {
+    _buffer_end = buffer + length;
+  }
+
+  static bool is_attr(u1* attr, const char* name) {
+    return strncmp((const char*)attr, name, strlen(name)) == 0;
+  }
+
+  static char* copy_attr(u1* value, size_t len) {
+    char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
+    strncpy(buf, (char*)value, len);
+    buf[len] = 0;
+    return buf;
+  }
+
+  // The return value indicates if the JAR is signed or not
+  bool check_is_signed() {
+    u1* attr = _current;
+    bool isSigned = false;
+    while (_current < _buffer_end) {
+      if (*_current == '\n') {
+        *_current = '\0';
+        u1* value = (u1*)strchr((char*)attr, ':');
+        if (value != NULL) {
+          assert(*(value+1) == ' ', "Unrecognized format" );
+          if (strstr((char*)attr, "-Digest") != NULL) {
+            isSigned = true;
+            break;
+          }
+        }
+        *_current = '\n'; // restore
+        attr = _current + 1;
+      }
+      _current ++;
+    }
+    return isSigned;
+  }
+};
+
+void FileMapInfo::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
+  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+  ResourceMark rm(THREAD);
+  jint manifest_size;
+  bool isSigned;
+
+  if (cpe->is_jar_file()) {
+    char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
+    if (manifest != NULL) {
+      ManifestStream* stream = new ManifestStream((u1*)manifest,
+                                                  manifest_size);
+      isSigned = stream->check_is_signed();
+      if (isSigned) {
+        ent->set_is_signed(true);
+      } else {
+        // Copy the manifest into the shared archive
+        manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
+        Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
+                                                        manifest_size,
+                                                        THREAD);
+        char* p = (char*)(buf->data());
+        memcpy(p, manifest, manifest_size);
+        ent->set_manifest(buf);
+        ent->set_is_signed(false);
+      }
+    }
+  }
+}
+
+
 bool FileMapInfo::validate_shared_path_table() {
   assert(UseSharedSpaces, "runtime only");
 
   _validating_shared_path_table = true;
   _shared_path_table = _header->_shared_path_table;
   _shared_path_entry_size = _header->_shared_path_entry_size;
   _shared_path_table_size = _header->_shared_path_table_size;
 
-  FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
-  int module_paths_start_index = header->_app_module_paths_start_index;
+  int module_paths_start_index = _header->_app_module_paths_start_index;
 
   // If the shared archive contain app or platform classes, validate all entries
   // in the shared path table. Otherwise, only validate the boot path entries (with
   // entry index < _app_class_paths_start_index).
-  int count = header->has_platform_or_app_classes() ?
-              _shared_path_table_size : header->_app_class_paths_start_index;
+  int count = _header->has_platform_or_app_classes() ?
+              _shared_path_table_size : _header->_app_class_paths_start_index;
 
   for (int i=0; i<count; i++) {
     if (i < module_paths_start_index) {
       if (shared_path(i)->validate()) {
         log_info(class, path)("ok");

@@ -1076,10 +1162,30 @@
                   _compact_strings ? "enabled" : "disabled",
                   CompactStrings   ? "enabled" : "disabled");
     return false;
   }
 
+  // This must be done after header validation because it might change the
+  // header data
+  const char* prop = Arguments::get_property("java.system.class.loader");
+  if (prop != NULL) {
+    warning("Archived non-system classes are disabled because the "
+            "java.system.class.loader property is specified (value = \"%s\"). "
+            "To use archived non-system classes, this property must be not be set", prop);
+    _has_platform_or_app_classes = false;
+  }
+
+  // For backwards compatibility, we don't check the verification setting
+  // if the archive only contains system classes.
+  if (_has_platform_or_app_classes &&
+      ((!_verify_local && BytecodeVerificationLocal) ||
+       (!_verify_remote && BytecodeVerificationRemote))) {
+    FileMapInfo::fail_continue("The shared archive file was created with less restrictive "
+                  "verification setting than the current setting.");
+    return false;
+  }
+
   return true;
 }
 
 bool FileMapInfo::validate_header() {
   bool status = _header->validate();
< prev index next >