mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 02:54:35 +02:00
8227370: Remove SharedPathsMiscInfo
Reviewed-by: ccheung, jiangli
This commit is contained in:
parent
11ca73d744
commit
87eefe2e00
16 changed files with 407 additions and 618 deletions
|
@ -241,7 +241,6 @@ void 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();
|
||||
_num_module_paths = ClassLoader::num_module_path_entries();
|
||||
|
@ -257,6 +256,11 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
|||
_base_archive_is_default = false;
|
||||
}
|
||||
|
||||
void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
|
||||
_type = non_existent_entry;
|
||||
set_name(path, THREAD);
|
||||
}
|
||||
|
||||
void SharedClassPathEntry::init(bool is_modules_image,
|
||||
ClassPathEntry* cpe, TRAPS) {
|
||||
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
|
||||
|
@ -288,26 +292,35 @@ void SharedClassPathEntry::init(bool is_modules_image,
|
|||
FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
|
||||
}
|
||||
|
||||
size_t len = strlen(cpe->name()) + 1;
|
||||
_name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD);
|
||||
strcpy(_name->data(), cpe->name());
|
||||
// No need to save the name of the module file, as it will be computed at run time
|
||||
// to allow relocation of the JDK directory.
|
||||
const char* name = is_modules_image ? "" : cpe->name();
|
||||
set_name(name, THREAD);
|
||||
}
|
||||
|
||||
bool SharedClassPathEntry::validate(bool is_class_path) {
|
||||
void SharedClassPathEntry::set_name(const char* name, TRAPS) {
|
||||
size_t len = strlen(name) + 1;
|
||||
_name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD);
|
||||
strcpy(_name->data(), name);
|
||||
}
|
||||
|
||||
const char* SharedClassPathEntry::name() const {
|
||||
if (UseSharedSpaces && is_modules_image()) {
|
||||
// In order to validate the runtime modules image file size against the archived
|
||||
// size information, we need to obtain the runtime modules image path. The recorded
|
||||
// dump time modules image path in the archive may be different from the runtime path
|
||||
// if the JDK image has beed moved after generating the archive.
|
||||
return ClassLoader::get_jrt_entry()->name();
|
||||
} else {
|
||||
return _name->data();
|
||||
}
|
||||
}
|
||||
|
||||
bool SharedClassPathEntry::validate(bool is_class_path) const {
|
||||
assert(UseSharedSpaces, "runtime only");
|
||||
|
||||
struct stat st;
|
||||
const char* name;
|
||||
|
||||
// In order to validate the runtime modules image file size against the archived
|
||||
// size information, we need to obtain the runtime modules image path. The recorded
|
||||
// dump time modules image path in the archive may be different from the runtime path
|
||||
// if the JDK image has beed moved after generating the archive.
|
||||
if (is_modules_image()) {
|
||||
name = ClassLoader::get_jrt_entry()->name();
|
||||
} else {
|
||||
name = this->name();
|
||||
}
|
||||
const char* name = this->name();
|
||||
|
||||
bool ok = true;
|
||||
log_info(class, path)("checking shared classpath entry: %s", name);
|
||||
|
@ -345,6 +358,19 @@ bool SharedClassPathEntry::validate(bool is_class_path) {
|
|||
return ok;
|
||||
}
|
||||
|
||||
bool SharedClassPathEntry::check_non_existent() const {
|
||||
assert(_type == non_existent_entry, "must be");
|
||||
log_info(class, path)("should be non-existent: %s", name());
|
||||
struct stat st;
|
||||
if (os::stat(name(), &st) != 0) {
|
||||
log_info(class, path)("ok");
|
||||
return true; // file doesn't exist
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SharedClassPathEntry::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
it->push(&_name);
|
||||
it->push(&_manifest);
|
||||
|
@ -359,10 +385,11 @@ void SharedPathTable::metaspace_pointers_do(MetaspaceClosure* it) {
|
|||
|
||||
void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD) {
|
||||
size_t entry_size = sizeof(SharedClassPathEntry);
|
||||
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;
|
||||
int num_entries = 0;
|
||||
num_entries += ClassLoader::num_boot_classpath_entries();
|
||||
num_entries += ClassLoader::num_app_classpath_entries();
|
||||
num_entries += ClassLoader::num_module_path_entries();
|
||||
num_entries += FileMapInfo::num_non_existent_class_paths();
|
||||
size_t bytes = entry_size * num_entries;
|
||||
|
||||
_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
|
||||
|
@ -372,7 +399,7 @@ void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD
|
|||
void FileMapInfo::allocate_shared_path_table() {
|
||||
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Sanity");
|
||||
|
||||
Thread* THREAD = Thread::current();
|
||||
EXCEPTION_MARK; // The following calls should never throw, but would exit VM on error.
|
||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||
ClassPathEntry* jrt = ClassLoader::get_jrt_entry();
|
||||
|
||||
|
@ -383,47 +410,37 @@ void FileMapInfo::allocate_shared_path_table() {
|
|||
|
||||
// 1. boot class path
|
||||
int i = 0;
|
||||
ClassPathEntry* cpe = jrt;
|
||||
i = add_shared_classpaths(i, "boot", jrt, THREAD);
|
||||
i = add_shared_classpaths(i, "app", ClassLoader::app_classpath_entries(), THREAD);
|
||||
i = add_shared_classpaths(i, "module", ClassLoader::module_path_entries(), THREAD);
|
||||
|
||||
for (int x = 0; x < num_non_existent_class_paths(); x++, i++) {
|
||||
const char* path = _non_existent_class_paths->at(x);
|
||||
shared_path(i)->init_as_non_existent(path, THREAD);
|
||||
}
|
||||
|
||||
assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
|
||||
}
|
||||
|
||||
int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) {
|
||||
while (cpe != NULL) {
|
||||
bool is_jrt = (cpe == jrt);
|
||||
bool is_jrt = (cpe == ClassLoader::get_jrt_entry());
|
||||
const char* type = (is_jrt ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
|
||||
log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
|
||||
log_info(class, path)("add %s shared path (%s) %s", which, type, cpe->name());
|
||||
SharedClassPathEntry* ent = shared_path(i);
|
||||
ent->init(is_jrt, cpe, THREAD);
|
||||
if (!is_jrt) { // No need to do the modules image.
|
||||
EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
|
||||
update_shared_classpath(cpe, ent, THREAD);
|
||||
if (cpe->is_jar_file()) {
|
||||
update_jar_manifest(cpe, ent, THREAD);
|
||||
}
|
||||
if (is_jrt) {
|
||||
cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
|
||||
} else {
|
||||
cpe = cpe->next();
|
||||
}
|
||||
cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
|
||||
i++;
|
||||
}
|
||||
assert(i == ClassLoader::num_boot_classpath_entries(),
|
||||
"number of boot class path entry mismatch");
|
||||
|
||||
// 2. app class path
|
||||
ClassPathEntry *acpe = ClassLoader::app_classpath_entries();
|
||||
while (acpe != NULL) {
|
||||
log_info(class, path)("add app shared path %s", acpe->name());
|
||||
SharedClassPathEntry* ent = shared_path(i);
|
||||
ent->init(false, acpe, THREAD);
|
||||
EXCEPTION_MARK;
|
||||
update_shared_classpath(acpe, ent, THREAD);
|
||||
acpe = acpe->next();
|
||||
i++;
|
||||
}
|
||||
|
||||
// 3. module path
|
||||
ClassPathEntry *mpe = ClassLoader::module_path_entries();
|
||||
while (mpe != NULL) {
|
||||
log_info(class, path)("add module path %s",mpe->name());
|
||||
SharedClassPathEntry* ent = shared_path(i);
|
||||
ent->init(false, mpe, THREAD);
|
||||
EXCEPTION_MARK;
|
||||
update_shared_classpath(mpe, ent, THREAD);
|
||||
mpe = mpe->next();
|
||||
i++;
|
||||
}
|
||||
assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
|
||||
return i;
|
||||
}
|
||||
|
||||
void FileMapInfo::check_nonempty_dir_in_shared_path_table() {
|
||||
|
@ -453,6 +470,24 @@ void FileMapInfo::check_nonempty_dir_in_shared_path_table() {
|
|||
}
|
||||
}
|
||||
|
||||
void FileMapInfo::record_non_existent_class_path_entry(const char* path) {
|
||||
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
|
||||
log_info(class, path)("non-existent Class-Path entry %s", path);
|
||||
if (_non_existent_class_paths == NULL) {
|
||||
_non_existent_class_paths = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<const char*>(10, true);
|
||||
}
|
||||
_non_existent_class_paths->append(os::strdup(path));
|
||||
}
|
||||
|
||||
int FileMapInfo::num_non_existent_class_paths() {
|
||||
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
|
||||
if (_non_existent_class_paths != NULL) {
|
||||
return _non_existent_class_paths->length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class ManifestStream: public ResourceObj {
|
||||
private:
|
||||
u1* _buffer_start; // Buffer bottom
|
||||
|
@ -501,29 +536,27 @@ class ManifestStream: public ResourceObj {
|
|||
}
|
||||
};
|
||||
|
||||
void FileMapInfo::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
|
||||
void FileMapInfo::update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
|
||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||
ResourceMark rm(THREAD);
|
||||
jint manifest_size;
|
||||
|
||||
if (cpe->is_jar_file()) {
|
||||
assert(ent->is_jar(), "the shared class path entry is not a JAR file");
|
||||
char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
|
||||
if (manifest != NULL) {
|
||||
ManifestStream* stream = new ManifestStream((u1*)manifest,
|
||||
manifest_size);
|
||||
if (stream->check_is_signed()) {
|
||||
ent->set_is_signed();
|
||||
} 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);
|
||||
}
|
||||
assert(cpe->is_jar_file() && ent->is_jar(), "the shared class path entry is not a JAR file");
|
||||
char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
|
||||
if (manifest != NULL) {
|
||||
ManifestStream* stream = new ManifestStream((u1*)manifest,
|
||||
manifest_size);
|
||||
if (stream->check_is_signed()) {
|
||||
ent->set_is_signed();
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -680,6 +713,16 @@ bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
|
|||
// None of the jar file specified in the runtime -cp exists.
|
||||
return fail("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
|
||||
}
|
||||
|
||||
// Handling of non-existent entries in the classpath: we eliminate all the non-existent
|
||||
// entries from both the dump time classpath (ClassLoader::update_class_path_entry_list)
|
||||
// and the runtime classpath (FileMapInfo::create_path_array), and check the remaining
|
||||
// entries. E.g.:
|
||||
//
|
||||
// dump : -cp a.jar:NE1:NE2:b.jar -> a.jar:b.jar -> recorded in archive.
|
||||
// run 1: -cp NE3:a.jar:NE4:b.jar -> a.jar:b.jar -> matched
|
||||
// run 2: -cp x.jar:NE4:b.jar -> x.jar:b.jar -> mismatched
|
||||
|
||||
int j = _header->_app_class_paths_start_index;
|
||||
mismatch = check_paths(j, shared_app_paths_len, rp_array);
|
||||
if (mismatch) {
|
||||
|
@ -689,6 +732,20 @@ bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FileMapInfo::log_paths(const char* msg, int start_idx, int end_idx) {
|
||||
LogTarget(Info, class, path) lt;
|
||||
if (lt.is_enabled()) {
|
||||
LogStream ls(lt);
|
||||
ls.print("%s", msg);
|
||||
const char* prefix = "";
|
||||
for (int i = start_idx; i < end_idx; i++) {
|
||||
ls.print("%s%s", prefix, shared_path(i)->name());
|
||||
prefix = os::path_separator();
|
||||
}
|
||||
ls.cr();
|
||||
}
|
||||
}
|
||||
|
||||
bool FileMapInfo::validate_shared_path_table() {
|
||||
assert(UseSharedSpaces, "runtime only");
|
||||
|
||||
|
@ -717,6 +774,9 @@ bool FileMapInfo::validate_shared_path_table() {
|
|||
}
|
||||
}
|
||||
|
||||
log_paths("Expecting BOOT path=", 0, _header->_app_class_paths_start_index);
|
||||
log_paths("Expecting -Djava.class.path=", _header->_app_class_paths_start_index, _header->_app_module_paths_start_index);
|
||||
|
||||
int module_paths_start_index = _header->_app_module_paths_start_index;
|
||||
int shared_app_paths_len = 0;
|
||||
|
||||
|
@ -757,6 +817,8 @@ bool FileMapInfo::validate_shared_path_table() {
|
|||
}
|
||||
}
|
||||
|
||||
validate_non_existent_class_paths();
|
||||
|
||||
_validating_shared_path_table = false;
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
|
@ -771,6 +833,26 @@ bool FileMapInfo::validate_shared_path_table() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FileMapInfo::validate_non_existent_class_paths() {
|
||||
// All of the recorded non-existent paths came from the Class-Path: attribute from the JAR
|
||||
// files on the app classpath. If any of these are found to exist during runtime,
|
||||
// it will change how classes are loading for the app loader. For safety, disable
|
||||
// loading of archived platform/app classes (currently there's no way to disable just the
|
||||
// app classes).
|
||||
|
||||
assert(UseSharedSpaces, "runtime only");
|
||||
for (int i = _header->_app_module_paths_start_index + _header->_num_module_paths;
|
||||
i < get_number_of_shared_paths();
|
||||
i++) {
|
||||
SharedClassPathEntry* ent = shared_path(i);
|
||||
if (!ent->check_non_existent()) {
|
||||
warning("Archived non-system classes are disabled because the "
|
||||
"file %s exists", ent->name());
|
||||
_header->_has_platform_or_app_classes = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
|
||||
int fd = os::open(archive_name, O_RDONLY | O_BINARY, 0);
|
||||
if (fd < 0) {
|
||||
|
@ -840,9 +922,6 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
|
|||
if (dynamic_header->_base_archive_is_default) {
|
||||
*base_archive_name = Arguments::get_default_shared_archive_path();
|
||||
} else {
|
||||
// skip over the _paths_misc_info
|
||||
sz = dynamic_header->_paths_misc_info_size;
|
||||
lseek(fd, (long)sz, SEEK_CUR);
|
||||
// read the base archive name
|
||||
size_t name_size = dynamic_header->_base_archive_name_size;
|
||||
if (name_size == 0) {
|
||||
|
@ -933,18 +1012,7 @@ bool FileMapInfo::init_from_file(int fd, bool is_static) {
|
|||
}
|
||||
}
|
||||
|
||||
_file_offset = n;
|
||||
|
||||
size_t info_size = _header->_paths_misc_info_size;
|
||||
_paths_misc_info = NEW_C_HEAP_ARRAY(char, info_size, mtClass);
|
||||
n = os::read(fd, _paths_misc_info, (unsigned int)info_size);
|
||||
if (n != info_size) {
|
||||
fail_continue("Unable to read the shared path info header.");
|
||||
FREE_C_HEAP_ARRAY(char, _paths_misc_info);
|
||||
_paths_misc_info = NULL;
|
||||
return false;
|
||||
}
|
||||
_file_offset += n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
|
||||
_file_offset = n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
|
||||
|
||||
if (is_static) {
|
||||
// just checking the last region is sufficient since the archive is written
|
||||
|
@ -1026,10 +1094,6 @@ void FileMapInfo::open_for_write(const char* path) {
|
|||
// Write the header to the file, seek to the next allocation boundary.
|
||||
|
||||
void FileMapInfo::write_header() {
|
||||
int info_size = ClassLoader::get_shared_paths_misc_info_size();
|
||||
|
||||
_header->_paths_misc_info_size = info_size;
|
||||
|
||||
char* base_archive_name = NULL;
|
||||
if (_header->_magic == CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
base_archive_name = (char*)Arguments::GetSharedArchivePath();
|
||||
|
@ -1039,7 +1103,6 @@ void FileMapInfo::write_header() {
|
|||
|
||||
assert(is_file_position_aligned(), "must be");
|
||||
write_bytes(_header, _header->_header_size);
|
||||
write_bytes(ClassLoader::get_shared_paths_misc_info(), (size_t)info_size);
|
||||
if (base_archive_name != NULL) {
|
||||
write_bytes(base_archive_name, (size_t)_header->_base_archive_name_size);
|
||||
}
|
||||
|
@ -1728,6 +1791,7 @@ bool FileMapInfo::_heap_pointers_need_patching = false;
|
|||
SharedPathTable FileMapInfo::_shared_path_table;
|
||||
bool FileMapInfo::_validating_shared_path_table = false;
|
||||
bool FileMapInfo::_memory_mapping_failed = false;
|
||||
GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = NULL;
|
||||
|
||||
// Open the shared archive file, read and validate the header
|
||||
// information (version, boot classpath, etc.). If initialization
|
||||
|
@ -1736,7 +1800,7 @@ bool FileMapInfo::_memory_mapping_failed = false;
|
|||
//
|
||||
// Validation of the archive is done in two steps:
|
||||
//
|
||||
// [1] validate_header() - done here. This checks the header, including _paths_misc_info.
|
||||
// [1] validate_header() - done here.
|
||||
// [2] validate_shared_path_table - this is done later, because the table is in the RW
|
||||
// region of the archive, which is not mapped yet.
|
||||
bool FileMapInfo::initialize(bool is_static) {
|
||||
|
@ -1840,22 +1904,7 @@ bool FileMapHeader::validate() {
|
|||
}
|
||||
|
||||
bool FileMapInfo::validate_header(bool is_static) {
|
||||
bool status = _header->validate();
|
||||
|
||||
if (status) {
|
||||
if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size, is_static)) {
|
||||
if (!PrintSharedArchiveAndExit) {
|
||||
fail_continue("shared class paths mismatch (hint: enable -Xlog:class+path=info to diagnose the failure)");
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_paths_misc_info != NULL) {
|
||||
FREE_C_HEAP_ARRAY(char, _paths_misc_info);
|
||||
_paths_misc_info = NULL;
|
||||
}
|
||||
return status;
|
||||
return _header->validate();
|
||||
}
|
||||
|
||||
// Check if a given address is within one of the shared regions
|
||||
|
@ -1907,7 +1956,7 @@ ClassPathEntry* FileMapInfo::get_classpath_entry_for_jvmti(int i, TRAPS) {
|
|||
ClassPathEntry* ent = _classpath_entries_for_jvmti[i];
|
||||
if (ent == NULL) {
|
||||
if (i == 0) {
|
||||
ent = ClassLoader:: get_jrt_entry();
|
||||
ent = ClassLoader::get_jrt_entry();
|
||||
assert(ent != NULL, "must be");
|
||||
} else {
|
||||
SharedClassPathEntry* scpe = shared_path(i);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue