8197954: Remove unnecessary intermediary APIs from AppCDS implementation
Reviewed-by: jiangli, ccheung
This commit is contained in:
parent
1ea9f48936
commit
e48f38966b
src/hotspot/share
classfile
classListParser.cppclassLoader.cppclassLoader.hppclassLoaderExt.cppclassLoaderExt.hppdictionary.cppklassFactory.cppsharedClassUtil.cppsharedClassUtil.hppsharedPathsMiscInfo.cppsharedPathsMiscInfo.hppsystemDictionary.cppsystemDictionary.hppsystemDictionaryShared.cppsystemDictionary_ext.hpp
memory
oops
prims
@ -27,7 +27,6 @@
|
||||
#include "jimage.hpp"
|
||||
#include "classfile/classListParser.hpp"
|
||||
#include "classfile/classLoaderExt.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
|
@ -72,7 +72,6 @@
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#if INCLUDE_CDS
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||
#endif
|
||||
|
||||
@ -660,7 +659,7 @@ void* ClassLoader::get_shared_paths_misc_info() {
|
||||
}
|
||||
|
||||
bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
|
||||
SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size);
|
||||
SharedPathsMiscInfo* checker = new SharedPathsMiscInfo((char*)buf, size);
|
||||
bool result = checker->check();
|
||||
delete checker;
|
||||
return result;
|
||||
@ -1406,8 +1405,6 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
|
||||
name->utf8_length());
|
||||
assert(file_name != NULL, "invariant");
|
||||
|
||||
ClassLoaderExt::Context context(class_name, file_name, THREAD);
|
||||
|
||||
// Lookup stream for parsing .class file
|
||||
ClassFileStream* stream = NULL;
|
||||
s2 classpath_index = 0;
|
||||
@ -1480,7 +1477,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream->set_verify(context.should_verify(classpath_index));
|
||||
stream->set_verify(ClassLoaderExt::should_verify(classpath_index));
|
||||
|
||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||
Handle protection_domain;
|
||||
@ -1628,8 +1625,7 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream
|
||||
ik->name()->utf8_length());
|
||||
assert(file_name != NULL, "invariant");
|
||||
|
||||
ClassLoaderExt::Context context(class_name, file_name, CATCH);
|
||||
context.record_result(ik->name(), classpath_index, ik, THREAD);
|
||||
ClassLoaderExt::record_result(classpath_index, ik, THREAD);
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
@ -1699,7 +1695,7 @@ void ClassLoader::initialize() {
|
||||
#if INCLUDE_CDS
|
||||
// initialize search path
|
||||
if (DumpSharedSpaces) {
|
||||
_shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info();
|
||||
_shared_paths_misc_info = new SharedPathsMiscInfo();
|
||||
}
|
||||
#endif
|
||||
setup_bootstrap_search_path();
|
||||
|
@ -426,8 +426,6 @@ class ClassLoader: AllStatic {
|
||||
static int get_shared_paths_misc_info_size();
|
||||
static void* get_shared_paths_misc_info();
|
||||
static bool check_shared_paths_misc_info(void* info, int size);
|
||||
static int get_module_paths_misc_info_size();
|
||||
static void* get_module_paths_misc_info();
|
||||
static void exit_with_path_failure(const char* error, const char* message);
|
||||
static char* skip_uri_protocol(char* source);
|
||||
static void record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/klassFactory.hpp"
|
||||
#include "classfile/modules.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
@ -57,8 +56,7 @@ bool ClassLoaderExt::_has_platform_classes = false;
|
||||
void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) {
|
||||
#if INCLUDE_CDS
|
||||
warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended");
|
||||
FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
|
||||
header->set_has_platform_or_app_classes(false);
|
||||
FileMapInfo::current_info()->header()->set_has_platform_or_app_classes(false);
|
||||
#endif
|
||||
ClassLoader::add_to_boot_append_entries(new_entry);
|
||||
}
|
||||
@ -228,11 +226,7 @@ void ClassLoaderExt::setup_search_paths() {
|
||||
ClassLoaderExt::setup_app_search_path();
|
||||
}
|
||||
|
||||
Thread* ClassLoaderExt::Context::_dump_thread = NULL;
|
||||
|
||||
void ClassLoaderExt::record_result(ClassLoaderExt::Context *context,
|
||||
Symbol* class_name,
|
||||
const s2 classpath_index,
|
||||
void ClassLoaderExt::record_result(const s2 classpath_index,
|
||||
InstanceKlass* result,
|
||||
TRAPS) {
|
||||
assert(DumpSharedSpaces, "Sanity");
|
||||
|
@ -29,74 +29,21 @@
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
CDS_ONLY(class SharedPathsMiscInfoExt;)
|
||||
CDS_ONLY(class ClassListParser;)
|
||||
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_class_paths_start_index if we're not using CDS.
|
||||
assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool should_verify(int classpath_index) {
|
||||
CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);)
|
||||
NOT_CDS(return false;)
|
||||
}
|
||||
|
||||
void record_result(Symbol* class_name,
|
||||
const s2 classpath_index,
|
||||
InstanceKlass* result,
|
||||
TRAPS) {
|
||||
#if INCLUDE_CDS
|
||||
ClassLoaderExt::record_result(this, class_name, classpath_index, result, THREAD);
|
||||
#endif
|
||||
}
|
||||
|
||||
~Context() {
|
||||
#if INCLUDE_CDS
|
||||
if (!DumpSharedSpaces && !UseSharedSpaces) {
|
||||
// Must not modify app_class_paths_start_index if we're not using CDS.
|
||||
assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
|
||||
}
|
||||
#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 void process_module_table(ModuleEntryTable* met, TRAPS);
|
||||
static SharedPathsMiscInfoExt* shared_paths_misc_info() {
|
||||
return (SharedPathsMiscInfoExt*)_shared_paths_misc_info;
|
||||
static SharedPathsMiscInfo* shared_paths_misc_info() {
|
||||
return (SharedPathsMiscInfo*)_shared_paths_misc_info;
|
||||
}
|
||||
// index of first app JAR in shared classpath entry table
|
||||
static jshort _app_class_paths_start_index;
|
||||
@ -110,6 +57,10 @@ private:
|
||||
public:
|
||||
CDS_ONLY(static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates);)
|
||||
|
||||
static bool should_verify(int classpath_index) {
|
||||
CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);)
|
||||
NOT_CDS(return false;)
|
||||
}
|
||||
// Called by JVMTI code to add boot classpath
|
||||
static void append_boot_classpath(ClassPathEntry* new_entry);
|
||||
|
||||
@ -156,9 +107,7 @@ public:
|
||||
return _has_app_classes || _has_platform_classes;
|
||||
}
|
||||
|
||||
static void record_result(class ClassLoaderExt::Context *context,
|
||||
Symbol* class_name,
|
||||
const s2 classpath_index,
|
||||
static void record_result(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);
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/dictionary.inline.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/klassFactory.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/jvmtiEnvBase.hpp"
|
||||
|
@ -1,255 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoaderExt.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
|
||||
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 SharedPathsMiscInfoExt::print_path(outputStream* out, int type, const char* path) {
|
||||
switch(type) {
|
||||
case APP:
|
||||
ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
|
||||
break;
|
||||
case MODULE:
|
||||
ClassLoader::trace_class_path("Checking module path: ", path);
|
||||
break;
|
||||
default:
|
||||
SharedPathsMiscInfo::print_path(out, type, path);
|
||||
}
|
||||
}
|
||||
|
||||
bool SharedPathsMiscInfoExt::check(jint type, const char* path) {
|
||||
|
||||
switch (type) {
|
||||
case APP:
|
||||
{
|
||||
// Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar
|
||||
size_t len = strlen(path);
|
||||
const char *appcp = Arguments::get_appclasspath();
|
||||
assert(appcp != NULL, "NULL app classpath");
|
||||
size_t appcp_len = strlen(appcp);
|
||||
if (appcp_len < len) {
|
||||
return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
|
||||
}
|
||||
ResourceMark rm;
|
||||
char* tmp_path;
|
||||
if (len == appcp_len) {
|
||||
tmp_path = (char*)appcp;
|
||||
} else {
|
||||
tmp_path = NEW_RESOURCE_ARRAY(char, len + 1);
|
||||
strncpy(tmp_path, appcp, len);
|
||||
tmp_path[len] = 0;
|
||||
}
|
||||
if (os::file_name_strcmp(path, tmp_path) != 0) {
|
||||
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
|
||||
}
|
||||
if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) {
|
||||
return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return SharedPathsMiscInfo::check(type, path);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharedClassUtil::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* e, TRAPS) {
|
||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||
SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)e;
|
||||
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->_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->_is_signed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharedClassUtil::initialize(TRAPS) {
|
||||
if (UseSharedSpaces) {
|
||||
int size = FileMapInfo::get_number_of_shared_paths();
|
||||
if (size > 0) {
|
||||
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
|
||||
FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
|
||||
ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
|
||||
ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (DumpSharedSpaces) {
|
||||
if (SharedArchiveConfigFile) {
|
||||
read_extra_data(SharedArchiveConfigFile, THREAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharedClassUtil::read_extra_data(const char* filename, TRAPS) {
|
||||
HashtableTextDump reader(filename);
|
||||
reader.check_version("VERSION: 1.0");
|
||||
|
||||
while (reader.remain() > 0) {
|
||||
int utf8_length;
|
||||
int prefix_type = reader.scan_prefix(&utf8_length);
|
||||
ResourceMark rm(THREAD);
|
||||
char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length);
|
||||
reader.get_utf8(utf8_buffer, utf8_length);
|
||||
|
||||
if (prefix_type == HashtableTextDump::SymbolPrefix) {
|
||||
SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD);
|
||||
} else{
|
||||
assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity");
|
||||
utf8_buffer[utf8_length] = '\0';
|
||||
oop s = StringTable::intern(utf8_buffer, THREAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) {
|
||||
assert(classpath_index >= 0, "Sanity");
|
||||
SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)
|
||||
FileMapInfo::shared_path(classpath_index);
|
||||
return ent->_is_signed;
|
||||
}
|
||||
|
||||
void FileMapHeaderExt::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
FileMapInfo::FileMapHeader::populate(mapinfo, alignment);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
bool FileMapHeaderExt::validate() {
|
||||
if (!FileMapInfo::FileMapHeader::validate()) {
|
||||
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;
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP
|
||||
#define SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP
|
||||
|
||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "classfile/classLoaderExt.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#include "oops/klass.hpp"
|
||||
|
||||
class FileMapHeaderExt: public FileMapInfo::FileMapHeader {
|
||||
public:
|
||||
jshort _app_class_paths_start_index; // Index of first app classpath entry
|
||||
jshort _app_module_paths_start_index; // Index of first module path entry
|
||||
bool _verify_local; // BytecodeVerificationLocal setting
|
||||
bool _verify_remote; // BytecodeVerificationRemote setting
|
||||
bool _has_platform_or_app_classes; // Archive contains app classes
|
||||
|
||||
FileMapHeaderExt() {
|
||||
_has_platform_or_app_classes = true;
|
||||
}
|
||||
void set_has_platform_or_app_classes(bool v) {
|
||||
_has_platform_or_app_classes = v;
|
||||
}
|
||||
bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
|
||||
virtual void populate(FileMapInfo* mapinfo, size_t alignment);
|
||||
virtual bool validate();
|
||||
};
|
||||
|
||||
// In addition to SharedPathsMiscInfo, the following information is also stored
|
||||
//
|
||||
//
|
||||
// + The value of Arguments::get_appclasspath() used during dumping.
|
||||
//
|
||||
class SharedPathsMiscInfoExt : public SharedPathsMiscInfo {
|
||||
private:
|
||||
int _app_offset;
|
||||
public:
|
||||
enum {
|
||||
APP = 5,
|
||||
MODULE = 6
|
||||
};
|
||||
|
||||
virtual const char* type_name(int type) {
|
||||
switch (type) {
|
||||
case APP: return "APP";
|
||||
case MODULE: return "MODULE";
|
||||
default: return SharedPathsMiscInfo::type_name(type);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void print_path(outputStream* out, int type, const char* path);
|
||||
|
||||
SharedPathsMiscInfoExt() : SharedPathsMiscInfo() {
|
||||
_app_offset = 0;
|
||||
}
|
||||
SharedPathsMiscInfoExt(char* buf, int size) : SharedPathsMiscInfo(buf, size) {
|
||||
_app_offset = 0;
|
||||
}
|
||||
|
||||
virtual bool check(jint type, const char* path);
|
||||
|
||||
void add_app_classpath(const char* path) {
|
||||
add_path(path, APP);
|
||||
}
|
||||
|
||||
void record_app_offset() {
|
||||
_app_offset = get_used_bytes();
|
||||
}
|
||||
void pop_app() {
|
||||
_cur_ptr = _buf_start + _app_offset;
|
||||
write_jint(0);
|
||||
}
|
||||
};
|
||||
|
||||
class SharedClassPathEntryExt: public SharedClassPathEntry {
|
||||
public:
|
||||
//Maniest attributes
|
||||
bool _is_signed;
|
||||
void set_manifest(Array<u1>* manifest) {
|
||||
_manifest = manifest;
|
||||
}
|
||||
};
|
||||
|
||||
class SharedClassUtil : AllStatic {
|
||||
public:
|
||||
static SharedPathsMiscInfo* allocate_shared_paths_misc_info() {
|
||||
return new SharedPathsMiscInfoExt();
|
||||
}
|
||||
|
||||
static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) {
|
||||
return new SharedPathsMiscInfoExt(buf, size);
|
||||
}
|
||||
|
||||
static FileMapInfo::FileMapHeader* allocate_file_map_header() {
|
||||
return new FileMapHeaderExt();
|
||||
}
|
||||
|
||||
static size_t file_map_header_size() {
|
||||
return sizeof(FileMapHeaderExt);
|
||||
}
|
||||
|
||||
static size_t shared_class_path_entry_size() {
|
||||
return sizeof(SharedClassPathEntryExt);
|
||||
}
|
||||
|
||||
static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
|
||||
static void initialize(TRAPS);
|
||||
|
||||
private:
|
||||
static void read_extra_data(const char* filename, TRAPS);
|
||||
|
||||
public:
|
||||
static bool is_classpath_entry_signed(int classpath_index);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
@ -36,6 +35,7 @@
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
SharedPathsMiscInfo::SharedPathsMiscInfo() {
|
||||
_app_offset = 0;
|
||||
_buf_size = INITIAL_BUF_SIZE;
|
||||
_cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass);
|
||||
_allocated = true;
|
||||
@ -89,12 +89,15 @@ bool SharedPathsMiscInfo::fail(const char* msg, const char* name) {
|
||||
|
||||
void SharedPathsMiscInfo::print_path(outputStream* out, int type, const char* path) {
|
||||
switch (type) {
|
||||
case BOOT:
|
||||
case BOOT_PATH:
|
||||
out->print("Expecting BOOT path=%s", path);
|
||||
break;
|
||||
case NON_EXIST:
|
||||
out->print("Expecting that %s does not exist", path);
|
||||
break;
|
||||
case APP_PATH:
|
||||
ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
@ -139,7 +142,7 @@ bool SharedPathsMiscInfo::check() {
|
||||
|
||||
bool SharedPathsMiscInfo::check(jint type, const char* path) {
|
||||
switch (type) {
|
||||
case BOOT:
|
||||
case BOOT_PATH:
|
||||
// In the future we should perform the check based on the content of the mapped archive.
|
||||
if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
|
||||
return fail("[BOOT classpath mismatch, actual =", Arguments::get_sysclasspath());
|
||||
@ -155,6 +158,33 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APP_PATH:
|
||||
{
|
||||
// Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar
|
||||
size_t len = strlen(path);
|
||||
const char *appcp = Arguments::get_appclasspath();
|
||||
assert(appcp != NULL, "NULL app classpath");
|
||||
size_t appcp_len = strlen(appcp);
|
||||
if (appcp_len < len) {
|
||||
return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
|
||||
}
|
||||
ResourceMark rm;
|
||||
char* tmp_path;
|
||||
if (len == appcp_len) {
|
||||
tmp_path = (char*)appcp;
|
||||
} else {
|
||||
tmp_path = NEW_RESOURCE_ARRAY(char, len + 1);
|
||||
strncpy(tmp_path, appcp, len);
|
||||
tmp_path[len] = 0;
|
||||
}
|
||||
if (os::file_name_strcmp(path, tmp_path) != 0) {
|
||||
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
|
||||
}
|
||||
if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) {
|
||||
return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return fail("Corrupted archive file header");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,8 +35,6 @@ class outputStream;
|
||||
//
|
||||
// + The values of Arguments::get_sysclasspath() used during dumping.
|
||||
//
|
||||
// + The meta-index file(s) used during dumping (incl modification time and size)
|
||||
//
|
||||
// + The class path elements specified during dumping but did not exist --
|
||||
// these elements must also be specified at run time, and they also must not
|
||||
// exist at run time.
|
||||
@ -53,6 +51,8 @@ class outputStream;
|
||||
// two situations. See below.
|
||||
|
||||
class SharedPathsMiscInfo : public CHeapObj<mtClass> {
|
||||
private:
|
||||
int _app_offset;
|
||||
protected:
|
||||
char* _buf_start;
|
||||
char* _cur_ptr;
|
||||
@ -67,7 +67,7 @@ protected:
|
||||
|
||||
protected:
|
||||
static bool fail(const char* msg, const char* name = NULL);
|
||||
virtual bool check(jint type, const char* path);
|
||||
bool check(jint type, const char* path);
|
||||
|
||||
public:
|
||||
enum {
|
||||
@ -77,6 +77,7 @@ public:
|
||||
SharedPathsMiscInfo();
|
||||
// This constructor is used when validating the misc info (during run time)
|
||||
SharedPathsMiscInfo(char *buff, int size) {
|
||||
_app_offset = 0;
|
||||
_cur_ptr = _buf_start = buff;
|
||||
_end_ptr = _buf_start + size;
|
||||
_buf_size = size;
|
||||
@ -100,8 +101,20 @@ public:
|
||||
|
||||
// The path must exist, and must contain exactly <num_entries> files/dirs
|
||||
void add_boot_classpath(const char* path) {
|
||||
add_path(path, BOOT);
|
||||
add_path(path, BOOT_PATH);
|
||||
}
|
||||
|
||||
void add_app_classpath(const char* path) {
|
||||
add_path(path, APP_PATH);
|
||||
}
|
||||
void record_app_offset() {
|
||||
_app_offset = get_used_bytes();
|
||||
}
|
||||
void pop_app() {
|
||||
_cur_ptr = _buf_start + _app_offset;
|
||||
write_jint(0);
|
||||
}
|
||||
|
||||
int write_jint(jint num) {
|
||||
write(&num, sizeof(num));
|
||||
return 0;
|
||||
@ -120,22 +133,24 @@ public:
|
||||
|
||||
// reading --
|
||||
|
||||
private:
|
||||
enum {
|
||||
BOOT = 1,
|
||||
NON_EXIST = 2
|
||||
BOOT_PATH = 1,
|
||||
APP_PATH = 2,
|
||||
NON_EXIST = 3
|
||||
};
|
||||
|
||||
virtual const char* type_name(int type) {
|
||||
const char* type_name(int type) {
|
||||
switch (type) {
|
||||
case BOOT: return "BOOT";
|
||||
case NON_EXIST: return "NON_EXIST";
|
||||
default: ShouldNotReachHere(); return "?";
|
||||
case BOOT_PATH: return "BOOT";
|
||||
case APP_PATH: return "APP";
|
||||
case NON_EXIST: return "NON_EXIST";
|
||||
default: ShouldNotReachHere(); return "?";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void print_path(outputStream* os, int type, const char* path);
|
||||
void print_path(outputStream* os, int type, const char* path);
|
||||
|
||||
bool check();
|
||||
bool read_jint(jint *ptr) {
|
||||
return read(ptr, sizeof(jint));
|
||||
}
|
||||
@ -145,6 +160,9 @@ public:
|
||||
bool read_time(time_t *ptr) {
|
||||
return read(ptr, sizeof(time_t));
|
||||
}
|
||||
|
||||
public:
|
||||
bool check();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
||||
|
@ -84,7 +84,6 @@
|
||||
#include "trace/tracing.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#if INCLUDE_CDS
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#endif
|
||||
#if INCLUDE_JVMCI
|
||||
|
@ -26,7 +26,6 @@
|
||||
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_HPP
|
||||
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/systemDictionary_ext.hpp"
|
||||
#include "jvmci/systemDictionary_jvmci.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
@ -186,6 +185,7 @@ class OopStorage;
|
||||
do_klass(File_klass, java_io_File, Pre ) \
|
||||
do_klass(URL_klass, java_net_URL, Pre ) \
|
||||
do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \
|
||||
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
|
||||
@ -212,8 +212,6 @@ class OopStorage;
|
||||
do_klass(Integer_klass, java_lang_Integer, Pre ) \
|
||||
do_klass(Long_klass, java_lang_Long, Pre ) \
|
||||
\
|
||||
/* Extensions */ \
|
||||
WK_KLASSES_DO_EXT(do_klass) \
|
||||
/* JVMCI classes. These are loaded on-demand. */ \
|
||||
JVMCI_WK_KLASSES_DO(do_klass) \
|
||||
\
|
||||
@ -223,7 +221,6 @@ class OopStorage;
|
||||
class SystemDictionary : AllStatic {
|
||||
friend class VMStructs;
|
||||
friend class SystemDictionaryHandles;
|
||||
friend class SharedClassUtil;
|
||||
|
||||
public:
|
||||
enum WKID {
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "classfile/compactHashtable.inline.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
@ -92,7 +91,7 @@ Handle SystemDictionaryShared::get_shared_jar_manifest(int shared_path_index, TR
|
||||
Handle empty;
|
||||
Handle manifest ;
|
||||
if (shared_jar_manifest(shared_path_index) == NULL) {
|
||||
SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_path(shared_path_index);
|
||||
SharedClassPathEntry* ent = FileMapInfo::shared_path(shared_path_index);
|
||||
long size = ent->manifest_size();
|
||||
if (size <= 0) {
|
||||
return empty; // No manifest - return NULL handle
|
||||
@ -303,8 +302,7 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
|
||||
if (ik != NULL) {
|
||||
int index = ik->shared_classpath_index();
|
||||
assert(index >= 0, "Sanity");
|
||||
SharedClassPathEntryExt* ent =
|
||||
(SharedClassPathEntryExt*)FileMapInfo::shared_path(index);
|
||||
SharedClassPathEntry* ent = FileMapInfo::shared_path(index);
|
||||
Symbol* class_name = ik->name();
|
||||
|
||||
if (ent->is_modules_image()) {
|
||||
@ -476,41 +474,38 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
|
||||
// [1] JVM_FindLoadedClass
|
||||
// [2] java.lang.ClassLoader.findLoadedClass0()
|
||||
// [3] java.lang.ClassLoader.findLoadedClass()
|
||||
// [4] java.lang.ClassLoader.loadClass()
|
||||
// [5] jdk.internal.loader.ClassLoaders$AppClassLoader_klass.loadClass()
|
||||
// [4] jdk.internal.loader.BuiltinClassLoader.loadClassOrNull()
|
||||
// [5] jdk.internal.loader.BuiltinClassLoader.loadClass()
|
||||
// [6] jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(), or
|
||||
// jdk.internal.loader.ClassLoaders$PlatformClassLoader.loadClass()
|
||||
//
|
||||
// Because AppCDS supports only the PlatformClassLoader and AppClassLoader, we make the following
|
||||
// assumptions (based on the JDK 8.0 source code):
|
||||
// AppCDS supports fast class loading for these 2 built-in class loaders:
|
||||
// jdk.internal.loader.ClassLoaders$PlatformClassLoader
|
||||
// jdk.internal.loader.ClassLoaders$AppClassLoader
|
||||
// with the following assumptions (based on the JDK core library source code):
|
||||
//
|
||||
// [a] these two loaders use the default implementation of
|
||||
// ClassLoader.loadClass(String name, boolean resolve), which
|
||||
// [b] calls findLoadedClass(name), immediately followed by parent.loadClass(),
|
||||
// immediately followed by findClass(name).
|
||||
// [c] If the requested class is a shared class of the current class loader, parent.loadClass()
|
||||
// always returns null, and
|
||||
// [d] if AppCDS is not enabled, the class would be loaded by findClass() by decoding it from a
|
||||
// JAR file and then parsed.
|
||||
// [a] these two loaders use the BuiltinClassLoader.loadClassOrNull() to
|
||||
// load the named class.
|
||||
// [b] BuiltinClassLoader.loadClassOrNull() first calls findLoadedClass(name).
|
||||
// [c] At this point, if we can find the named class inside the
|
||||
// shared_dictionary, we can perform further checks (see
|
||||
// is_shared_class_visible_for_classloader() to ensure that this class
|
||||
// was loaded by the same class loader during dump time.
|
||||
//
|
||||
// Given these assumptions, we intercept the findLoadedClass() call to invoke
|
||||
// SystemDictionaryShared::find_or_load_shared_class() to load the shared class from
|
||||
// the archive. The reasons are:
|
||||
//
|
||||
// + Because AppCDS is a commercial feature, we want to hide the implementation. There
|
||||
// is currently no easy way to hide Java code, so we did it with native code.
|
||||
// + Start-up is improved because we avoid decoding the JAR file, and avoid delegating
|
||||
// to the parent (since we know the parent will not find this class).
|
||||
// the archive for the 2 built-in class loaders. This way,
|
||||
// we can improve start-up because we avoid decoding the classfile,
|
||||
// and avoid delegating to the parent loader.
|
||||
//
|
||||
// NOTE: there's a lot of assumption about the Java code. If any of that change, this
|
||||
// needs to be redesigned.
|
||||
//
|
||||
// An alternative is to modify the Java code of AppClassLoader.loadClass().
|
||||
//
|
||||
|
||||
InstanceKlass* SystemDictionaryShared::find_or_load_shared_class(
|
||||
Symbol* name, Handle class_loader, TRAPS) {
|
||||
InstanceKlass* k = NULL;
|
||||
if (UseSharedSpaces) {
|
||||
FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
|
||||
if (!header->has_platform_or_app_classes()) {
|
||||
if (!FileMapInfo::current_info()->header()->has_platform_or_app_classes()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
|
||||
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
|
||||
|
||||
#if INCLUDE_CDS
|
||||
|
||||
#define WK_KLASSES_DO_EXT(do_klass) \
|
||||
/* well-known classes */ \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \
|
||||
/*end*/
|
||||
|
||||
#else
|
||||
|
||||
#define WK_KLASSES_DO_EXT(do_klass)
|
||||
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
|
@ -25,8 +25,8 @@
|
||||
#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"
|
||||
@ -159,8 +159,9 @@ FileMapInfo::FileMapInfo() {
|
||||
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() {
|
||||
@ -172,10 +173,6 @@ 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);
|
||||
}
|
||||
|
||||
void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
_magic = 0xf00baba2;
|
||||
_version = _current_version;
|
||||
@ -198,6 +195,14 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment
|
||||
|
||||
// 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) {
|
||||
@ -278,7 +283,7 @@ void FileMapInfo::allocate_shared_path_table() {
|
||||
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();
|
||||
@ -299,7 +304,7 @@ void FileMapInfo::allocate_shared_path_table() {
|
||||
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++;
|
||||
@ -314,7 +319,7 @@ void FileMapInfo::allocate_shared_path_table() {
|
||||
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++;
|
||||
}
|
||||
@ -326,7 +331,7 @@ void FileMapInfo::allocate_shared_path_table() {
|
||||
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++;
|
||||
}
|
||||
@ -360,6 +365,84 @@ void FileMapInfo::check_nonempty_dir_in_shared_path_table() {
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
@ -368,14 +451,13 @@ bool FileMapInfo::validate_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) {
|
||||
@ -1078,6 +1160,26 @@ bool FileMapInfo::FileMapHeader::validate() {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ protected:
|
||||
long _filesize; // jar/jimage file size, -1 if is directory, -2 if other
|
||||
Array<char>* _name;
|
||||
Array<u1>* _manifest;
|
||||
bool _is_signed;
|
||||
|
||||
public:
|
||||
void init(const char* name, TRAPS);
|
||||
@ -70,6 +71,15 @@ public:
|
||||
int manifest_size() const {
|
||||
return (_manifest == NULL) ? 0 : _manifest->length();
|
||||
}
|
||||
void set_manifest(Array<u1>* manifest) {
|
||||
_manifest = manifest;
|
||||
}
|
||||
void set_is_signed(bool s) {
|
||||
_is_signed = s;
|
||||
}
|
||||
bool is_signed() {
|
||||
return _is_signed;
|
||||
}
|
||||
};
|
||||
|
||||
class FileMapInfo : public CHeapObj<mtInternal> {
|
||||
@ -97,13 +107,16 @@ private:
|
||||
|
||||
public:
|
||||
struct FileMapHeaderBase : public CHeapObj<mtClass> {
|
||||
virtual bool validate() = 0;
|
||||
virtual void populate(FileMapInfo* info, size_t alignment) = 0;
|
||||
// Need to put something here. Otherwise, in product build, because CHeapObj has no virtual
|
||||
// methods, we would get sizeof(FileMapHeaderBase) == 1 with gcc.
|
||||
intx _dummy;
|
||||
};
|
||||
struct FileMapHeader : FileMapHeaderBase {
|
||||
// Use data() and data_size() to memcopy to/from the FileMapHeader. We need to
|
||||
// avoid read/writing the C++ vtable pointer.
|
||||
static size_t data_size();
|
||||
static size_t data_size() {
|
||||
return sizeof(FileMapHeader) - sizeof(FileMapInfo::FileMapHeaderBase);
|
||||
}
|
||||
char* data() {
|
||||
return ((char*)this) + sizeof(FileMapHeaderBase);
|
||||
}
|
||||
@ -146,7 +159,7 @@ public:
|
||||
|
||||
// The _paths_misc_info is a variable-size structure that records "miscellaneous"
|
||||
// information during dumping. It is generated and validated by the
|
||||
// SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp and sharedClassUtil.hpp for
|
||||
// SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for
|
||||
// detailed description.
|
||||
//
|
||||
// The _paths_misc_info data is stored as a byte array in the archive file header,
|
||||
@ -172,10 +185,21 @@ public:
|
||||
size_t _shared_path_entry_size;
|
||||
Array<u8>* _shared_path_table;
|
||||
|
||||
jshort _app_class_paths_start_index; // Index of first app classpath entry
|
||||
jshort _app_module_paths_start_index; // Index of first module path entry
|
||||
bool _verify_local; // BytecodeVerificationLocal setting
|
||||
bool _verify_remote; // BytecodeVerificationRemote setting
|
||||
bool _has_platform_or_app_classes; // Archive contains app classes
|
||||
|
||||
void set_has_platform_or_app_classes(bool v) {
|
||||
_has_platform_or_app_classes = v;
|
||||
}
|
||||
bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
|
||||
|
||||
char* region_addr(int idx);
|
||||
|
||||
virtual bool validate();
|
||||
virtual void populate(FileMapInfo* info, size_t alignment);
|
||||
bool validate();
|
||||
void populate(FileMapInfo* info, size_t alignment);
|
||||
int compute_crc();
|
||||
};
|
||||
|
||||
@ -274,6 +298,7 @@ public:
|
||||
static void allocate_shared_path_table();
|
||||
static void check_nonempty_dir_in_shared_path_table();
|
||||
bool validate_shared_path_table();
|
||||
static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
|
||||
|
||||
static SharedClassPathEntry* shared_path(int index) {
|
||||
if (index < 0) {
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/loaderConstraints.hpp"
|
||||
#include "classfile/placeholders.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
@ -323,6 +322,46 @@ void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
|
||||
_shared_rs.size(), p2i(_shared_rs.base()));
|
||||
}
|
||||
|
||||
// Called by universe_post_init()
|
||||
void MetaspaceShared::post_initialize(TRAPS) {
|
||||
if (UseSharedSpaces) {
|
||||
int size = FileMapInfo::get_number_of_shared_paths();
|
||||
if (size > 0) {
|
||||
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
|
||||
FileMapInfo::FileMapHeader* header = FileMapInfo::current_info()->header();
|
||||
ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
|
||||
ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (DumpSharedSpaces) {
|
||||
if (SharedArchiveConfigFile) {
|
||||
read_extra_data(SharedArchiveConfigFile, THREAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MetaspaceShared::read_extra_data(const char* filename, TRAPS) {
|
||||
HashtableTextDump reader(filename);
|
||||
reader.check_version("VERSION: 1.0");
|
||||
|
||||
while (reader.remain() > 0) {
|
||||
int utf8_length;
|
||||
int prefix_type = reader.scan_prefix(&utf8_length);
|
||||
ResourceMark rm(THREAD);
|
||||
char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length);
|
||||
reader.get_utf8(utf8_buffer, utf8_length);
|
||||
|
||||
if (prefix_type == HashtableTextDump::SymbolPrefix) {
|
||||
SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD);
|
||||
} else{
|
||||
assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity");
|
||||
utf8_buffer[utf8_length] = '\0';
|
||||
oop s = StringTable::intern(utf8_buffer, THREAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MetaspaceShared::commit_shared_space_to(char* newtop) {
|
||||
assert(DumpSharedSpaces, "dump-time only");
|
||||
char* base = _shared_rs.base();
|
||||
|
@ -147,6 +147,7 @@ class MetaspaceShared : AllStatic {
|
||||
}
|
||||
static void initialize_dumptime_shared_and_meta_spaces() NOT_CDS_RETURN;
|
||||
static void initialize_runtime_shared_and_meta_spaces() NOT_CDS_RETURN;
|
||||
static void post_initialize(TRAPS) NOT_CDS_RETURN;
|
||||
|
||||
// Delta of this object from the bottom of the archive.
|
||||
static uintx object_delta(void* obj) {
|
||||
@ -250,5 +251,8 @@ class MetaspaceShared : AllStatic {
|
||||
static void relocate_klass_ptr(oop o);
|
||||
|
||||
static Klass* get_relocated_klass(Klass *k);
|
||||
|
||||
private:
|
||||
static void read_extra_data(const char* filename, TRAPS) NOT_CDS_RETURN;
|
||||
};
|
||||
#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
|
||||
|
@ -81,9 +81,6 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#include "utilities/preserveException.hpp"
|
||||
#if INCLUDE_CDS
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#endif
|
||||
|
||||
// Known objects
|
||||
Klass* Universe::_boolArrayKlassObj = NULL;
|
||||
@ -1094,7 +1091,7 @@ bool universe_post_init() {
|
||||
|
||||
MemoryService::set_universe_heap(Universe::heap());
|
||||
#if INCLUDE_CDS
|
||||
SharedClassUtil::initialize(CHECK_false);
|
||||
MetaspaceShared::post_initialize(CHECK_false);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -168,7 +168,6 @@ private:
|
||||
// in the open archive heap region when archiving java object is supported.
|
||||
CDS_JAVA_HEAP_ONLY(narrowOop _archived_mirror;)
|
||||
|
||||
friend class SharedClassUtil;
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
|
@ -84,7 +84,6 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/utf8.hpp"
|
||||
#if INCLUDE_CDS
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user