src/hotspot/share/classfile/sharedClassUtil.cpp
branchhttp-client-branch
changeset 56539 a738880f0bd8
parent 56538 9bdcfc7d2b9c
parent 50073 35b22ca681d1
child 56556 46bb98e9db71
equal deleted inserted replaced
56538:9bdcfc7d2b9c 56539:a738880f0bd8
     1 /*
       
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "classfile/classLoader.hpp"
       
    27 #include "classfile/classLoaderExt.hpp"
       
    28 #include "classfile/dictionary.hpp"
       
    29 #include "classfile/javaClasses.hpp"
       
    30 #include "classfile/sharedClassUtil.hpp"
       
    31 #include "classfile/stringTable.hpp"
       
    32 #include "classfile/symbolTable.hpp"
       
    33 #include "classfile/systemDictionary.hpp"
       
    34 #include "classfile/systemDictionaryShared.hpp"
       
    35 #include "memory/filemap.hpp"
       
    36 #include "memory/metadataFactory.hpp"
       
    37 #include "memory/resourceArea.hpp"
       
    38 #include "oops/instanceKlass.hpp"
       
    39 #include "runtime/arguments.hpp"
       
    40 #include "runtime/java.hpp"
       
    41 #include "runtime/os.inline.hpp"
       
    42 
       
    43 class ManifestStream: public ResourceObj {
       
    44   private:
       
    45   u1*   _buffer_start; // Buffer bottom
       
    46   u1*   _buffer_end;   // Buffer top (one past last element)
       
    47   u1*   _current;      // Current buffer position
       
    48 
       
    49  public:
       
    50   // Constructor
       
    51   ManifestStream(u1* buffer, int length) : _buffer_start(buffer),
       
    52                                            _current(buffer) {
       
    53     _buffer_end = buffer + length;
       
    54   }
       
    55 
       
    56   static bool is_attr(u1* attr, const char* name) {
       
    57     return strncmp((const char*)attr, name, strlen(name)) == 0;
       
    58   }
       
    59 
       
    60   static char* copy_attr(u1* value, size_t len) {
       
    61     char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
       
    62     strncpy(buf, (char*)value, len);
       
    63     buf[len] = 0;
       
    64     return buf;
       
    65   }
       
    66 
       
    67   // The return value indicates if the JAR is signed or not
       
    68   bool check_is_signed() {
       
    69     u1* attr = _current;
       
    70     bool isSigned = false;
       
    71     while (_current < _buffer_end) {
       
    72       if (*_current == '\n') {
       
    73         *_current = '\0';
       
    74         u1* value = (u1*)strchr((char*)attr, ':');
       
    75         if (value != NULL) {
       
    76           assert(*(value+1) == ' ', "Unrecognized format" );
       
    77           if (strstr((char*)attr, "-Digest") != NULL) {
       
    78             isSigned = true;
       
    79             break;
       
    80           }
       
    81         }
       
    82         *_current = '\n'; // restore
       
    83         attr = _current + 1;
       
    84       }
       
    85       _current ++;
       
    86     }
       
    87     return isSigned;
       
    88   }
       
    89 };
       
    90 
       
    91 void SharedPathsMiscInfoExt::print_path(outputStream* out, int type, const char* path) {
       
    92   switch(type) {
       
    93   case APP:
       
    94     ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
       
    95     break;
       
    96   case MODULE:
       
    97     ClassLoader::trace_class_path("Checking module path: ", path);
       
    98     break;
       
    99   default:
       
   100     SharedPathsMiscInfo::print_path(out, type, path);
       
   101   }
       
   102 }
       
   103 
       
   104 bool SharedPathsMiscInfoExt::check(jint type, const char* path) {
       
   105 
       
   106   switch (type) {
       
   107   case APP:
       
   108     {
       
   109       // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar
       
   110       size_t len = strlen(path);
       
   111       const char *appcp = Arguments::get_appclasspath();
       
   112       assert(appcp != NULL, "NULL app classpath");
       
   113       size_t appcp_len = strlen(appcp);
       
   114       if (appcp_len < len) {
       
   115         return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
       
   116       }
       
   117       ResourceMark rm;
       
   118       char* tmp_path;
       
   119       if (len == appcp_len) {
       
   120         tmp_path = (char*)appcp;
       
   121       } else {
       
   122         tmp_path = NEW_RESOURCE_ARRAY(char, len + 1);
       
   123         strncpy(tmp_path, appcp, len);
       
   124         tmp_path[len] = 0;
       
   125       }
       
   126       if (os::file_name_strcmp(path, tmp_path) != 0) {
       
   127         return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
       
   128       }
       
   129       if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) {
       
   130         return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp);
       
   131       }
       
   132     }
       
   133     break;
       
   134   default:
       
   135     return SharedPathsMiscInfo::check(type, path);
       
   136   }
       
   137 
       
   138   return true;
       
   139 }
       
   140 
       
   141 void SharedClassUtil::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* e, TRAPS) {
       
   142   ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
       
   143   SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)e;
       
   144   ResourceMark rm(THREAD);
       
   145   jint manifest_size;
       
   146   bool isSigned;
       
   147 
       
   148   if (cpe->is_jar_file()) {
       
   149     char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
       
   150     if (manifest != NULL) {
       
   151       ManifestStream* stream = new ManifestStream((u1*)manifest,
       
   152                                                   manifest_size);
       
   153       isSigned = stream->check_is_signed();
       
   154       if (isSigned) {
       
   155         ent->_is_signed = true;
       
   156       } else {
       
   157         // Copy the manifest into the shared archive
       
   158         manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
       
   159         Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
       
   160                                                         manifest_size,
       
   161                                                         THREAD);
       
   162         char* p = (char*)(buf->data());
       
   163         memcpy(p, manifest, manifest_size);
       
   164         ent->set_manifest(buf);
       
   165         ent->_is_signed = false;
       
   166       }
       
   167     }
       
   168   }
       
   169 }
       
   170 
       
   171 void SharedClassUtil::initialize(TRAPS) {
       
   172   if (UseSharedSpaces) {
       
   173     int size = FileMapInfo::get_number_of_shared_paths();
       
   174     if (size > 0) {
       
   175       SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
       
   176       FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
       
   177       ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
       
   178       ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
       
   179     }
       
   180   }
       
   181 
       
   182   if (DumpSharedSpaces) {
       
   183     if (SharedArchiveConfigFile) {
       
   184       read_extra_data(SharedArchiveConfigFile, THREAD);
       
   185     }
       
   186   }
       
   187 }
       
   188 
       
   189 void SharedClassUtil::read_extra_data(const char* filename, TRAPS) {
       
   190   HashtableTextDump reader(filename);
       
   191   reader.check_version("VERSION: 1.0");
       
   192 
       
   193   while (reader.remain() > 0) {
       
   194     int utf8_length;
       
   195     int prefix_type = reader.scan_prefix(&utf8_length);
       
   196     ResourceMark rm(THREAD);
       
   197     char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length);
       
   198     reader.get_utf8(utf8_buffer, utf8_length);
       
   199 
       
   200     if (prefix_type == HashtableTextDump::SymbolPrefix) {
       
   201       SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD);
       
   202     } else{
       
   203       assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity");
       
   204       utf8_buffer[utf8_length] = '\0';
       
   205       oop s = StringTable::intern(utf8_buffer, THREAD);
       
   206     }
       
   207   }
       
   208 }
       
   209 
       
   210 bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) {
       
   211   assert(classpath_index >= 0, "Sanity");
       
   212   SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)
       
   213     FileMapInfo::shared_path(classpath_index);
       
   214   return ent->_is_signed;
       
   215 }
       
   216 
       
   217 void FileMapHeaderExt::populate(FileMapInfo* mapinfo, size_t alignment) {
       
   218   FileMapInfo::FileMapHeader::populate(mapinfo, alignment);
       
   219 
       
   220   ClassLoaderExt::finalize_shared_paths_misc_info();
       
   221   _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
       
   222   _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
       
   223 
       
   224   _verify_local = BytecodeVerificationLocal;
       
   225   _verify_remote = BytecodeVerificationRemote;
       
   226   _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
       
   227 }
       
   228 
       
   229 bool FileMapHeaderExt::validate() {
       
   230   if (!FileMapInfo::FileMapHeader::validate()) {
       
   231     return false;
       
   232   }
       
   233 
       
   234   // This must be done after header validation because it might change the
       
   235   // header data
       
   236   const char* prop = Arguments::get_property("java.system.class.loader");
       
   237   if (prop != NULL) {
       
   238     warning("Archived non-system classes are disabled because the "
       
   239             "java.system.class.loader property is specified (value = \"%s\"). "
       
   240             "To use archived non-system classes, this property must be not be set", prop);
       
   241     _has_platform_or_app_classes = false;
       
   242   }
       
   243 
       
   244   // For backwards compatibility, we don't check the verification setting
       
   245   // if the archive only contains system classes.
       
   246   if (_has_platform_or_app_classes &&
       
   247       ((!_verify_local && BytecodeVerificationLocal) ||
       
   248        (!_verify_remote && BytecodeVerificationRemote))) {
       
   249     FileMapInfo::fail_continue("The shared archive file was created with less restrictive "
       
   250                   "verification setting than the current setting.");
       
   251     return false;
       
   252   }
       
   253 
       
   254   return true;
       
   255 }