mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-11 14:11:36 +00:00
8227370: Remove SharedPathsMiscInfo
Reviewed-by: ccheung, jiangli
This commit is contained in:
parent
11ca73d744
commit
87eefe2e00
@ -73,9 +73,6 @@
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#if INCLUDE_CDS
|
||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||
#endif
|
||||
|
||||
// Entry points in zip.dll for loading zip/jar file entries
|
||||
|
||||
@ -147,7 +144,6 @@ ClassPathEntry* ClassLoader::_app_classpath_entries = NULL;
|
||||
ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
|
||||
ClassPathEntry* ClassLoader::_module_path_entries = NULL;
|
||||
ClassPathEntry* ClassLoader::_last_module_path_entry = NULL;
|
||||
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
|
||||
#endif
|
||||
|
||||
// helper routines
|
||||
@ -250,13 +246,12 @@ PackageEntry* ClassLoader::get_package_entry(const char* class_name, ClassLoader
|
||||
return pkgEntryTable->lookup_only(pkg_symbol);
|
||||
}
|
||||
|
||||
ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
|
||||
char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
|
||||
strcpy(copy, dir);
|
||||
_dir = copy;
|
||||
const char* ClassPathEntry::copy_path(const char* path) {
|
||||
char* copy = NEW_C_HEAP_ARRAY(char, strlen(path)+1, mtClass);
|
||||
strcpy(copy, path);
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
|
||||
// construct full path name
|
||||
assert((_dir != NULL) && (name != NULL), "sanity");
|
||||
@ -296,9 +291,7 @@ ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
|
||||
ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name,
|
||||
bool is_boot_append, bool from_class_path_attr) : ClassPathEntry() {
|
||||
_zip = zip;
|
||||
char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
|
||||
strcpy(copy, zip_name);
|
||||
_zip_name = copy;
|
||||
_zip_name = copy_path(zip_name);
|
||||
_from_class_path_attr = from_class_path_attr;
|
||||
}
|
||||
|
||||
@ -383,8 +376,7 @@ ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
|
||||
assert(_singleton == NULL, "VM supports only one jimage");
|
||||
DEBUG_ONLY(_singleton = this);
|
||||
size_t len = strlen(name) + 1;
|
||||
_name = NEW_C_HEAP_ARRAY(const char, len, mtClass);
|
||||
strncpy((char *)_name, name, len);
|
||||
_name = copy_path(name);
|
||||
}
|
||||
|
||||
ClassPathImageEntry::~ClassPathImageEntry() {
|
||||
@ -537,30 +529,10 @@ void ClassLoader::setup_bootstrap_search_path() {
|
||||
} else {
|
||||
trace_class_path("bootstrap loader class path=", sys_class_path);
|
||||
}
|
||||
#if INCLUDE_CDS
|
||||
if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
|
||||
_shared_paths_misc_info->add_boot_classpath(sys_class_path);
|
||||
}
|
||||
#endif
|
||||
setup_boot_search_path(sys_class_path);
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
int ClassLoader::get_shared_paths_misc_info_size() {
|
||||
return _shared_paths_misc_info->get_used_bytes();
|
||||
}
|
||||
|
||||
void* ClassLoader::get_shared_paths_misc_info() {
|
||||
return _shared_paths_misc_info->buffer();
|
||||
}
|
||||
|
||||
bool ClassLoader::check_shared_paths_misc_info(void *buf, int size, bool is_static) {
|
||||
SharedPathsMiscInfo* checker = new SharedPathsMiscInfo((char*)buf, size);
|
||||
bool result = checker->check(is_static);
|
||||
delete checker;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ClassLoader::setup_app_search_path(const char *class_path) {
|
||||
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Sanity");
|
||||
|
||||
@ -943,11 +915,6 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
#if INCLUDE_CDS
|
||||
if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
|
||||
_shared_paths_misc_info->add_nonexist_path(path);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1567,12 +1534,6 @@ void ClassLoader::initialize() {
|
||||
load_zip_library();
|
||||
// lookup jimage library entry points
|
||||
load_jimage_library();
|
||||
#if INCLUDE_CDS
|
||||
// initialize search path
|
||||
if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
|
||||
_shared_paths_misc_info = new SharedPathsMiscInfo();
|
||||
}
|
||||
#endif
|
||||
setup_bootstrap_search_path();
|
||||
}
|
||||
|
||||
@ -1580,7 +1541,6 @@ void ClassLoader::initialize() {
|
||||
void ClassLoader::initialize_shared_path() {
|
||||
if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
|
||||
ClassLoaderExt::setup_search_paths();
|
||||
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,17 +47,19 @@ template <typename T> class GrowableArray;
|
||||
class ClassPathEntry : public CHeapObj<mtClass> {
|
||||
private:
|
||||
ClassPathEntry* volatile _next;
|
||||
protected:
|
||||
const char* copy_path(const char*path);
|
||||
public:
|
||||
ClassPathEntry* next() const;
|
||||
virtual ~ClassPathEntry() {}
|
||||
void set_next(ClassPathEntry* next);
|
||||
virtual bool is_modules_image() const = 0;
|
||||
virtual bool is_jar_file() const = 0;
|
||||
virtual bool is_modules_image() const { return false; }
|
||||
virtual bool is_jar_file() const { return false; }
|
||||
// Is this entry created from the "Class-path" attribute from a JAR Manifest?
|
||||
virtual bool from_class_path_attr() const = 0;
|
||||
virtual bool from_class_path_attr() const { return false; }
|
||||
virtual const char* name() const = 0;
|
||||
virtual JImageFile* jimage() const = 0;
|
||||
virtual void close_jimage() = 0;
|
||||
virtual JImageFile* jimage() const { return NULL; }
|
||||
virtual void close_jimage() {}
|
||||
// Constructor
|
||||
ClassPathEntry() : _next(NULL) {}
|
||||
// Attempt to locate file_name through this class path entry.
|
||||
@ -73,18 +75,14 @@ class ClassPathDirEntry: public ClassPathEntry {
|
||||
private:
|
||||
const char* _dir; // Name of directory
|
||||
public:
|
||||
bool is_modules_image() const { return false; }
|
||||
bool is_jar_file() const { return false; }
|
||||
bool from_class_path_attr() const { return false; }
|
||||
const char* name() const { return _dir; }
|
||||
JImageFile* jimage() const { return NULL; }
|
||||
void close_jimage() {}
|
||||
ClassPathDirEntry(const char* dir);
|
||||
ClassPathDirEntry(const char* dir) {
|
||||
_dir = copy_path(dir);
|
||||
}
|
||||
virtual ~ClassPathDirEntry() {}
|
||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
};
|
||||
|
||||
|
||||
// Type definitions for zip file and zip file entry
|
||||
typedef void* jzfile;
|
||||
typedef struct {
|
||||
@ -104,12 +102,9 @@ class ClassPathZipEntry: public ClassPathEntry {
|
||||
const char* _zip_name; // Name of zip archive
|
||||
bool _from_class_path_attr; // From the "Class-path" attribute of a jar file
|
||||
public:
|
||||
bool is_modules_image() const { return false; }
|
||||
bool is_jar_file() const { return true; }
|
||||
bool from_class_path_attr() const { return _from_class_path_attr; }
|
||||
const char* name() const { return _zip_name; }
|
||||
JImageFile* jimage() const { return NULL; }
|
||||
void close_jimage() {}
|
||||
ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append, bool from_class_path_attr);
|
||||
virtual ~ClassPathZipEntry();
|
||||
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||
@ -126,8 +121,6 @@ private:
|
||||
DEBUG_ONLY(static ClassPathImageEntry* _singleton;)
|
||||
public:
|
||||
bool is_modules_image() const;
|
||||
bool is_jar_file() const { return false; }
|
||||
bool from_class_path_attr() const { return false; }
|
||||
bool is_open() const { return _jimage != NULL; }
|
||||
const char* name() const { return _name == NULL ? "" : _name; }
|
||||
JImageFile* jimage() const { return _jimage; }
|
||||
@ -156,8 +149,6 @@ public:
|
||||
void add_to_list(ClassPathEntry* new_entry);
|
||||
};
|
||||
|
||||
class SharedPathsMiscInfo;
|
||||
|
||||
class ClassLoader: AllStatic {
|
||||
public:
|
||||
enum ClassLoaderType {
|
||||
@ -230,8 +221,6 @@ class ClassLoader: AllStatic {
|
||||
static ClassPathEntry* _last_append_entry;
|
||||
|
||||
// Info used by CDS
|
||||
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
|
||||
|
||||
CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
|
||||
CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;)
|
||||
CDS_ONLY(static ClassPathEntry* _module_path_entries;)
|
||||
@ -416,10 +405,6 @@ class ClassLoader: AllStatic {
|
||||
}
|
||||
return num_entries;
|
||||
}
|
||||
static void finalize_shared_paths_misc_info();
|
||||
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, bool is_static);
|
||||
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);
|
||||
|
||||
@ -30,7 +30,6 @@
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/klassFactory.hpp"
|
||||
#include "classfile/modules.hpp"
|
||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
@ -74,7 +73,6 @@ void ClassLoaderExt::setup_app_search_path() {
|
||||
trace_class_path("app loader class path (skipped)=", app_class_path);
|
||||
} else {
|
||||
trace_class_path("app loader class path=", app_class_path);
|
||||
shared_paths_misc_info()->add_app_classpath(app_class_path);
|
||||
ClassLoader::setup_app_search_path(app_class_path);
|
||||
}
|
||||
}
|
||||
@ -212,8 +210,12 @@ void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry,
|
||||
char* libname = NEW_RESOURCE_ARRAY(char, libname_len + 1);
|
||||
int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
|
||||
assert((size_t)n == libname_len, "Unexpected number of characters in string");
|
||||
trace_class_path("library = ", libname);
|
||||
ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */);
|
||||
if (ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */)) {
|
||||
trace_class_path("library = ", libname);
|
||||
} else {
|
||||
trace_class_path("library (non-existent) = ", libname);
|
||||
FileMapInfo::record_non_existent_class_path_entry(libname);
|
||||
}
|
||||
}
|
||||
|
||||
file_start = file_end;
|
||||
@ -222,7 +224,6 @@ void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry,
|
||||
}
|
||||
|
||||
void ClassLoaderExt::setup_search_paths() {
|
||||
shared_paths_misc_info()->record_app_offset();
|
||||
ClassLoaderExt::setup_app_search_path();
|
||||
}
|
||||
|
||||
@ -248,12 +249,6 @@ void ClassLoaderExt::record_result(const s2 classpath_index,
|
||||
result->set_class_loader_type(classloader_type);
|
||||
}
|
||||
|
||||
void ClassLoaderExt::finalize_shared_paths_misc_info() {
|
||||
if (!_has_app_classes) {
|
||||
shared_paths_misc_info()->pop_app();
|
||||
}
|
||||
}
|
||||
|
||||
// Load the class of the given name from the location given by path. The path is specified by
|
||||
// the "source:" in the class list file (see classListParser.cpp), and can be a directory or
|
||||
// a JAR file.
|
||||
|
||||
@ -47,9 +47,6 @@ private:
|
||||
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 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;
|
||||
// index of first modular JAR in shared modulepath entry table
|
||||
@ -84,8 +81,6 @@ public:
|
||||
return read_manifest(entry, manifest_size, false, THREAD);
|
||||
}
|
||||
|
||||
static void finalize_shared_paths_misc_info();
|
||||
|
||||
static jshort app_class_paths_start_index() { return _app_class_paths_start_index; }
|
||||
|
||||
static jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
|
||||
|
||||
@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, 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/sharedPathsMiscInfo.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
#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;
|
||||
}
|
||||
|
||||
SharedPathsMiscInfo::~SharedPathsMiscInfo() {
|
||||
if (_allocated) {
|
||||
FREE_C_HEAP_ARRAY(char, _buf_start);
|
||||
}
|
||||
}
|
||||
|
||||
void SharedPathsMiscInfo::add_path(const char* path, int type) {
|
||||
log_info(class, path)("type=%s ", type_name(type));
|
||||
ClassLoader::trace_class_path("add misc shared path ", path);
|
||||
write(path, strlen(path) + 1);
|
||||
write_jint(jint(type));
|
||||
}
|
||||
|
||||
void SharedPathsMiscInfo::ensure_size(size_t needed_bytes) {
|
||||
assert(_allocated, "cannot modify buffer during validation.");
|
||||
int used = get_used_bytes();
|
||||
int target = used + int(needed_bytes);
|
||||
if (target > _buf_size) {
|
||||
_buf_size = _buf_size * 2 + (int)needed_bytes;
|
||||
_buf_start = REALLOC_C_HEAP_ARRAY(char, _buf_start, _buf_size, mtClass);
|
||||
_cur_ptr = _buf_start + used;
|
||||
_end_ptr = _buf_start + _buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
void SharedPathsMiscInfo::write(const void* ptr, size_t size) {
|
||||
ensure_size(size);
|
||||
memcpy(_cur_ptr, ptr, size);
|
||||
_cur_ptr += size;
|
||||
}
|
||||
|
||||
bool SharedPathsMiscInfo::read(void* ptr, size_t size) {
|
||||
if (_cur_ptr + size <= _end_ptr) {
|
||||
memcpy(ptr, _cur_ptr, size);
|
||||
_cur_ptr += size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SharedPathsMiscInfo::fail(const char* msg, const char* name) {
|
||||
ClassLoader::trace_class_path(msg, name);
|
||||
MetaspaceShared::set_archive_loading_failed();
|
||||
return false;
|
||||
}
|
||||
|
||||
void SharedPathsMiscInfo::print_path(outputStream* out, int type, const char* path) {
|
||||
switch (type) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
bool SharedPathsMiscInfo::check(bool is_static) {
|
||||
// The whole buffer must be 0 terminated so that we can use strlen and strcmp
|
||||
// without fear.
|
||||
_end_ptr -= sizeof(jint);
|
||||
if (_cur_ptr >= _end_ptr) {
|
||||
return fail("Truncated archive file header");
|
||||
}
|
||||
if (*_end_ptr != 0) {
|
||||
return fail("Corrupted archive file header");
|
||||
}
|
||||
|
||||
jshort cur_index = 0;
|
||||
FileMapHeader* header = is_static ? FileMapInfo::current_info()->header() :
|
||||
FileMapInfo::dynamic_info()->header();
|
||||
jshort max_cp_index = header->max_used_path_index();
|
||||
jshort module_paths_start_index = header->app_module_paths_start_index();
|
||||
while (_cur_ptr < _end_ptr) {
|
||||
jint type;
|
||||
const char* path = _cur_ptr;
|
||||
_cur_ptr += strlen(path) + 1;
|
||||
|
||||
if (!read_jint(&type)) {
|
||||
return fail("Corrupted archive file header");
|
||||
}
|
||||
LogTarget(Info, class, path) lt;
|
||||
if (lt.is_enabled()) {
|
||||
lt.print("type=%s ", type_name(type));
|
||||
LogStream ls(lt);
|
||||
print_path(&ls, type, path);
|
||||
ls.cr();
|
||||
}
|
||||
// skip checking the class path(s) which was not referenced during CDS dump
|
||||
if ((cur_index <= max_cp_index) || (cur_index >= module_paths_start_index)) {
|
||||
if (!check(type, path, is_static)) {
|
||||
if (!PrintSharedArchiveAndExit) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ClassLoader::trace_class_path("ok");
|
||||
}
|
||||
} else {
|
||||
ClassLoader::trace_class_path("skipped check");
|
||||
}
|
||||
cur_index++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedPathsMiscInfo::check(jint type, const char* path, bool is_static) {
|
||||
assert(UseSharedSpaces, "runtime only");
|
||||
switch (type) {
|
||||
case BOOT_PATH:
|
||||
break;
|
||||
case NON_EXIST:
|
||||
{
|
||||
struct stat st;
|
||||
if (os::stat(path, &st) == 0) {
|
||||
// The file actually exists
|
||||
// But we want it to not exist -> fail
|
||||
return fail("File must not exist");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APP_PATH:
|
||||
break;
|
||||
default:
|
||||
return fail("Corrupted archive file header");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, 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_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
||||
#define SHARE_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
||||
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
class outputStream;
|
||||
// During dumping time, when processing class paths, we build up the dump-time
|
||||
// classpath. The JAR files that exist are stored in the list ClassLoader::_first_append_entry.
|
||||
// However, we need to store other "misc" information for run-time checking, such as
|
||||
//
|
||||
// + The values of Arguments::get_sysclasspath() used during dumping.
|
||||
//
|
||||
// + 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.
|
||||
//
|
||||
// These misc items are stored in a linear buffer in SharedPathsMiscInfo.
|
||||
// The storage format is stream oriented to minimize its size.
|
||||
//
|
||||
// When writing the information to the archive file, SharedPathsMiscInfo is stored in
|
||||
// the archive file header. At run-time, this information is used only during initialization
|
||||
// (accessed using read() instead of mmap()), and is deallocated afterwards to save space.
|
||||
//
|
||||
// The SharedPathsMiscInfo class is used for both creating the the information (during
|
||||
// dumping time) and validation (at run time). Different constructors are used in the
|
||||
// two situations. See below.
|
||||
|
||||
class SharedPathsMiscInfo : public CHeapObj<mtClass> {
|
||||
private:
|
||||
int _app_offset;
|
||||
protected:
|
||||
char* _buf_start;
|
||||
char* _cur_ptr;
|
||||
char* _end_ptr;
|
||||
int _buf_size;
|
||||
bool _allocated; // was _buf_start allocated by me?
|
||||
void ensure_size(size_t needed_bytes);
|
||||
void add_path(const char* path, int type);
|
||||
|
||||
void write(const void* ptr, size_t size);
|
||||
bool read(void* ptr, size_t size);
|
||||
|
||||
protected:
|
||||
static bool fail(const char* msg, const char* name = NULL);
|
||||
bool check(jint type, const char* path, bool is_static);
|
||||
|
||||
public:
|
||||
enum {
|
||||
INITIAL_BUF_SIZE = 128
|
||||
};
|
||||
// This constructor is used when creating the misc information (during dump)
|
||||
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;
|
||||
_allocated = false;
|
||||
}
|
||||
~SharedPathsMiscInfo();
|
||||
|
||||
int get_used_bytes() {
|
||||
return _cur_ptr - _buf_start;
|
||||
}
|
||||
void* buffer() {
|
||||
return _buf_start;
|
||||
}
|
||||
|
||||
// writing --
|
||||
|
||||
// The path must not exist at run-time
|
||||
void add_nonexist_path(const char* path) {
|
||||
add_path(path, NON_EXIST);
|
||||
}
|
||||
|
||||
// The path must exist, and must contain exactly <num_entries> files/dirs
|
||||
void add_boot_classpath(const char* path) {
|
||||
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;
|
||||
}
|
||||
void write_time(time_t t) {
|
||||
write(&t, sizeof(t));
|
||||
}
|
||||
void write_long(long l) {
|
||||
write(&l, sizeof(l));
|
||||
}
|
||||
|
||||
bool dump_to_file(int fd) {
|
||||
int n = get_used_bytes();
|
||||
return (os::write(fd, _buf_start, n) == (size_t)n);
|
||||
}
|
||||
|
||||
// reading --
|
||||
|
||||
private:
|
||||
enum {
|
||||
BOOT_PATH = 1,
|
||||
APP_PATH = 2,
|
||||
NON_EXIST = 3
|
||||
};
|
||||
|
||||
const char* type_name(int type) {
|
||||
switch (type) {
|
||||
case BOOT_PATH: return "BOOT";
|
||||
case APP_PATH: return "APP";
|
||||
case NON_EXIST: return "NON_EXIST";
|
||||
default: ShouldNotReachHere(); return "?";
|
||||
}
|
||||
}
|
||||
|
||||
void print_path(outputStream* os, int type, const char* path);
|
||||
|
||||
bool read_jint(jint *ptr) {
|
||||
return read(ptr, sizeof(jint));
|
||||
}
|
||||
bool read_long(long *ptr) {
|
||||
return read(ptr, sizeof(long));
|
||||
}
|
||||
bool read_time(time_t *ptr) {
|
||||
return read(ptr, sizeof(time_t));
|
||||
}
|
||||
|
||||
public:
|
||||
bool check(bool is_static);
|
||||
};
|
||||
|
||||
#endif // SHARE_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
||||
@ -36,7 +36,7 @@
|
||||
#define NUM_CDS_REGIONS 8 // this must be the same as MetaspaceShared::n_regions
|
||||
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
||||
#define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 6
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 7
|
||||
#define INVALID_CDS_ARCHIVE_VERSION -1
|
||||
|
||||
struct CDSFileMapRegion {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -49,8 +49,12 @@ class SharedClassPathEntry {
|
||||
jar_entry,
|
||||
signed_jar_entry,
|
||||
dir_entry,
|
||||
non_existent_entry,
|
||||
unknown_entry
|
||||
};
|
||||
|
||||
void set_name(const char* name, TRAPS);
|
||||
|
||||
protected:
|
||||
u1 _type;
|
||||
bool _from_class_path_attr;
|
||||
@ -61,24 +65,25 @@ protected:
|
||||
|
||||
public:
|
||||
void init(bool is_modules_image, ClassPathEntry* cpe, TRAPS);
|
||||
void init_as_non_existent(const char* path, TRAPS);
|
||||
void metaspace_pointers_do(MetaspaceClosure* it);
|
||||
bool validate(bool is_class_path = true);
|
||||
bool validate(bool is_class_path = true) const;
|
||||
|
||||
// The _timestamp only gets set for jar files.
|
||||
bool has_timestamp() {
|
||||
bool has_timestamp() const {
|
||||
return _timestamp != 0;
|
||||
}
|
||||
bool is_dir() { return _type == dir_entry; }
|
||||
bool is_modules_image() { return _type == modules_image_entry; }
|
||||
bool is_jar() { return _type == jar_entry; }
|
||||
bool is_signed() { return _type == signed_jar_entry; }
|
||||
void set_is_signed() {
|
||||
bool is_dir() const { return _type == dir_entry; }
|
||||
bool is_modules_image() const { return _type == modules_image_entry; }
|
||||
bool is_jar() const { return _type == jar_entry; }
|
||||
bool is_signed() const { return _type == signed_jar_entry; }
|
||||
void set_is_signed() {
|
||||
_type = signed_jar_entry;
|
||||
}
|
||||
bool from_class_path_attr() { return _from_class_path_attr; }
|
||||
time_t timestamp() const { return _timestamp; }
|
||||
long filesize() const { return _filesize; }
|
||||
const char* name() const { return _name->data(); }
|
||||
const char* name() const;
|
||||
const char* manifest() const {
|
||||
return (_manifest == NULL) ? NULL : (const char*)_manifest->data();
|
||||
}
|
||||
@ -88,6 +93,7 @@ public:
|
||||
void set_manifest(Array<u1>* manifest) {
|
||||
_manifest = manifest;
|
||||
}
|
||||
bool check_non_existent() const;
|
||||
};
|
||||
|
||||
struct ArchiveHeapOopmapInfo {
|
||||
@ -147,30 +153,12 @@ struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
// size of the base archive name including NULL terminator
|
||||
int _base_archive_name_size;
|
||||
|
||||
// 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 for
|
||||
// detailed description.
|
||||
//
|
||||
// The _paths_misc_info data is stored as a byte array in the archive file header,
|
||||
// immediately after the _header field. This information is used only when
|
||||
// checking the validity of the archive and is deallocated after the archive is loaded.
|
||||
//
|
||||
// Note that the _paths_misc_info does NOT include information for JAR files
|
||||
// that existed during dump time. Their information is stored in _shared_path_table.
|
||||
int _paths_misc_info_size;
|
||||
|
||||
// The following is a table of all the class path entries that were used
|
||||
// during dumping. At run time, we require these files to exist and have the same
|
||||
// size/modification time, or else the archive will refuse to load.
|
||||
//
|
||||
// All of these entries must be JAR files. The dumping process would fail if a non-empty
|
||||
// directory was specified in the classpaths. If an empty directory was specified
|
||||
// it is checked by the _paths_misc_info as described above.
|
||||
//
|
||||
// FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
|
||||
// they should be removed from this table, to save space and to avoid spurious
|
||||
// loading failures during runtime.
|
||||
// The following is a table of all the boot/app/module path entries that were used
|
||||
// during dumping. At run time, we validate these entries according to their
|
||||
// SharedClassPathEntry::_type. See:
|
||||
// check_nonempty_dir_in_shared_path_table()
|
||||
// validate_shared_path_table()
|
||||
// validate_non_existent_class_paths()
|
||||
SharedPathTable _shared_path_table;
|
||||
|
||||
jshort _app_class_paths_start_index; // Index of first app classpath entry
|
||||
@ -232,13 +220,14 @@ public:
|
||||
FileMapHeader * _header;
|
||||
|
||||
const char* _full_path;
|
||||
char* _paths_misc_info;
|
||||
char* _base_archive_name;
|
||||
|
||||
static FileMapInfo* _current_info;
|
||||
static FileMapInfo* _dynamic_archive_info;
|
||||
static bool _heap_pointers_need_patching;
|
||||
static bool _memory_mapping_failed;
|
||||
static GrowableArray<const char*>* _non_existent_class_paths;
|
||||
|
||||
static bool get_base_archive_name_from_header(const char* archive_name,
|
||||
int* size, char** base_archive_name);
|
||||
static bool check_archive(const char* archive_name, bool is_static);
|
||||
@ -246,6 +235,8 @@ public:
|
||||
bool init_from_file(int fd, bool is_static);
|
||||
static void metaspace_pointers_do(MetaspaceClosure* it);
|
||||
|
||||
void log_paths(const char* msg, int start_idx, int end_idx);
|
||||
|
||||
public:
|
||||
FileMapInfo(bool is_static);
|
||||
~FileMapInfo();
|
||||
@ -353,9 +344,13 @@ public:
|
||||
static void stop_sharing_and_unmap(const char* msg);
|
||||
|
||||
static void allocate_shared_path_table();
|
||||
static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS);
|
||||
static void check_nonempty_dir_in_shared_path_table();
|
||||
bool validate_shared_path_table();
|
||||
static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
|
||||
void validate_non_existent_class_paths();
|
||||
static void update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
|
||||
static int num_non_existent_class_paths();
|
||||
static void record_non_existent_class_path_entry(const char* path);
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
static ClassFileStream* open_stream_for_jvmti(InstanceKlass* ik, Handle class_loader, TRAPS);
|
||||
|
||||
@ -53,7 +53,6 @@ CDSOffsets* CDSOffsets::_all = NULL;
|
||||
ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapHeader, _space)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapHeader, _paths_misc_info_size)); \
|
||||
ADD_NEXT(_all, "file_header_size", sizeof(FileMapHeader)); \
|
||||
ADD_NEXT(_all, "DynamicArchiveHeader::_base_archive_crc", offset_of(DynamicArchiveHeader, _base_archive_crc)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion_size", sizeof(CDSFileMapRegion));
|
||||
|
||||
@ -95,19 +95,5 @@ public class AppendClasspath {
|
||||
"-cp", appJar2 + File.pathSeparator + appJar,
|
||||
"HelloMore")
|
||||
.assertAbnormalExit(errorMessage1, errorMessage2);
|
||||
|
||||
// FAIL: 4) non-existing jar during dump time but jar exists during runtime
|
||||
TestCommon.testDump(classPath, TestCommon.list("Hello"));
|
||||
|
||||
Files.copy(Paths.get(classDir, "hello.jar"),
|
||||
Paths.get(classDir, newFile),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
TestCommon.run(
|
||||
"-cp", classPath,
|
||||
"-Xlog:class+path=trace",
|
||||
"Hello")
|
||||
.assertAbnormalExit(errorMessage1, errorMessage2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +42,11 @@ import java.nio.file.Paths;
|
||||
public class ClassPathAttr {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testNormalOps();
|
||||
testNonExistentJars();
|
||||
}
|
||||
|
||||
static void testNormalOps() throws Exception {
|
||||
buildCpAttr("cpattr1", "cpattr1.mf", "CpAttr1", "CpAttr1");
|
||||
buildCpAttr("cpattr1_long", "cpattr1_long.mf", "CpAttr1", "CpAttr1");
|
||||
buildCpAttr("cpattr2", "cpattr2.mf", "CpAttr2", "CpAttr2");
|
||||
@ -93,6 +98,37 @@ public class ClassPathAttr {
|
||||
}
|
||||
}
|
||||
|
||||
static void testNonExistentJars() throws Exception {
|
||||
buildCpAttr("cpattr6", "cpattr6.mf", "CpAttr6", "CpAttr6");
|
||||
|
||||
String cp = TestCommon.getTestJar("cpattr6.jar");
|
||||
String nonExistPath = System.getProperty("test.classes") + File.separator + "cpattrX.jar";
|
||||
(new File(nonExistPath)).delete();
|
||||
|
||||
TestCommon.testDump(cp, TestCommon.list("CpAttr6"),
|
||||
"-Xlog:class+path");
|
||||
|
||||
TestCommon.run(
|
||||
"-Xlog:class+path",
|
||||
"-cp", cp,
|
||||
"CpAttr6")
|
||||
.assertNormalExit(output -> {
|
||||
output.shouldMatch("should be non-existent: .*cpattrX.jar");
|
||||
});
|
||||
|
||||
// Now make nonExistPath exist. CDS still loads, but archived non-system classes will not be used.
|
||||
Files.copy(Paths.get(cp), Paths.get(nonExistPath),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
TestCommon.run(
|
||||
"-Xlog:class+path",
|
||||
"-cp", cp,
|
||||
"CpAttr6")
|
||||
.assertNormalExit(output -> {
|
||||
output.shouldMatch("Archived non-system classes are disabled because the file .*cpattrX.jar exists");
|
||||
});
|
||||
}
|
||||
|
||||
private static void buildCpAttr(String jarName, String manifest, String enclosingClassName, String ...testClassNames) throws Exception {
|
||||
String jarClassesDir = System.getProperty("test.classes") + File.separator + jarName + "_classes";
|
||||
try { Files.createDirectory(Paths.get(jarClassesDir)); } catch (FileAlreadyExistsException e) { }
|
||||
|
||||
115
test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java
Normal file
115
test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Handling of non-existent classpath elements during dump time and run time
|
||||
* @requires vm.cds
|
||||
* @library /test/lib
|
||||
* @modules jdk.jartool/sun.tools.jar
|
||||
* @compile test-classes/Hello.java
|
||||
* @compile test-classes/HelloMore.java
|
||||
* @run driver NonExistClasspath
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class NonExistClasspath {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String appJar = JarBuilder.getOrCreateHelloJar();
|
||||
doTest(appJar, false);
|
||||
doTest(appJar, true);
|
||||
}
|
||||
|
||||
static void doTest(String appJar, boolean bootcp) throws Exception {
|
||||
String classDir = System.getProperty("test.classes");
|
||||
String newFile = "non-exist.jar";
|
||||
String nonExistPath = classDir + File.separator + newFile;
|
||||
final String errorMessage1 = "Unable to use shared archive";
|
||||
final String errorMessage2 = "shared class paths mismatch";
|
||||
final String errorMessage3 = (bootcp ? "BOOT" : "APP") + " classpath mismatch";
|
||||
|
||||
(new File(nonExistPath)).delete();
|
||||
|
||||
String classPath = nonExistPath + File.pathSeparator + appJar;
|
||||
TestCommon.testDump("foobar", TestCommon.list("Hello"), make_args(bootcp, classPath));
|
||||
|
||||
// The nonExistPath doesn't exist yet, so we should be able to run without problem
|
||||
TestCommon.run(make_args(bootcp,
|
||||
classPath,
|
||||
"-Xlog:class+path=trace",
|
||||
"Hello"))
|
||||
.assertNormalExit();
|
||||
|
||||
// Replace nonExistPath with another non-existent file in the CP, it should still work
|
||||
TestCommon.run(make_args(bootcp,
|
||||
nonExistPath + ".duh" + File.pathSeparator + appJar,
|
||||
"-Xlog:class+path=trace",
|
||||
"Hello"))
|
||||
.assertNormalExit();
|
||||
|
||||
// Add a few more non-existent files in the CP, it should still work
|
||||
TestCommon.run(make_args(bootcp,
|
||||
nonExistPath + ".duh" + File.pathSeparator +
|
||||
nonExistPath + ".daa" + File.pathSeparator +
|
||||
nonExistPath + ".boo" + File.pathSeparator +
|
||||
appJar,
|
||||
"-Xlog:class+path=trace",
|
||||
"Hello"))
|
||||
.assertNormalExit();
|
||||
|
||||
// Or, remove all non-existent paths from the CP, it should still work
|
||||
TestCommon.run(make_args(bootcp,
|
||||
appJar,
|
||||
"-Xlog:class+path=trace",
|
||||
"Hello"))
|
||||
.assertNormalExit();
|
||||
|
||||
// Now make nonExistPath exist. CDS will fail to load.
|
||||
Files.copy(Paths.get(classDir, "hello.jar"),
|
||||
Paths.get(classDir, newFile),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
TestCommon.run(make_args(bootcp,
|
||||
classPath,
|
||||
"-Xlog:class+path=trace",
|
||||
"Hello"))
|
||||
.assertAbnormalExit(errorMessage1, errorMessage2, errorMessage3);
|
||||
}
|
||||
|
||||
static String[] make_args(boolean bootcp, String cp, String... suffix) {
|
||||
String args[];
|
||||
if (bootcp) {
|
||||
args = TestCommon.concat("-Xbootclasspath/a:" + cp);
|
||||
} else {
|
||||
args = TestCommon.concat("-cp", cp);
|
||||
}
|
||||
|
||||
return TestCommon.concat(args, suffix);
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,6 @@ public class SharedArchiveConsistency {
|
||||
public static int offset_version; // CDSFileMapHeaderBase::_version
|
||||
public static int offset_jvm_ident; // FileMapHeader::_jvm_ident
|
||||
public static int sp_offset_crc; // CDSFileMapRegion::_crc
|
||||
public static int offset_paths_misc_info_size;
|
||||
public static int file_header_size = -1;// total size of header, variant, need calculation
|
||||
public static int CDSFileMapRegion_size; // size of CDSFileMapRegion
|
||||
public static int sp_offset; // offset of CDSFileMapRegion
|
||||
@ -117,12 +116,6 @@ public class SharedArchiveConsistency {
|
||||
// this is not real header size, it is struct size
|
||||
int_size = wb.getOffsetForName("int_size");
|
||||
file_header_size = wb.getOffsetForName("file_header_size");
|
||||
offset_paths_misc_info_size = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") -
|
||||
offset_magic;
|
||||
int path_misc_info_size = (int)readInt(fc, offset_paths_misc_info_size, int_size);
|
||||
file_header_size += path_misc_info_size;
|
||||
System.out.println("offset_paths_misc_info_size = " + offset_paths_misc_info_size);
|
||||
System.out.println("path_misc_info_size = " + path_misc_info_size);
|
||||
System.out.println("file_header_size = " + file_header_size);
|
||||
file_header_size = (int)align_up_page(file_header_size);
|
||||
System.out.println("file_header_size (aligned to page) = " + file_header_size);
|
||||
@ -405,10 +398,9 @@ public class SharedArchiveConsistency {
|
||||
output.shouldNotContain("Checksum verification failed");
|
||||
|
||||
copyFile(orgJsaFile, jsa);
|
||||
// modify _jvm_ident and _paths_misc_info_size, test should fail
|
||||
System.out.println("\n2a. Corrupt _jvm_ident and _paths_misc_info_size, should fail\n");
|
||||
// modify _jvm_ident, test should fail
|
||||
System.out.println("\n2a. Corrupt _jvm_ident, should fail\n");
|
||||
modifyJvmIdent();
|
||||
modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
|
||||
output = TestCommon.execCommon(execArgs);
|
||||
output.shouldContain("The shared archive file was created by a different version or build of HotSpot");
|
||||
output.shouldNotContain("Checksum verification failed");
|
||||
@ -422,19 +414,17 @@ public class SharedArchiveConsistency {
|
||||
output.shouldContain("Hello World");
|
||||
|
||||
copyFile(orgJsaFile, jsa);
|
||||
// modify _magic and _paths_misc_info_size, test should fail
|
||||
System.out.println("\n2c. Corrupt _magic and _paths_misc_info_size, should fail\n");
|
||||
// modify _magic, test should fail
|
||||
System.out.println("\n2c. Corrupt _magic, should fail\n");
|
||||
modifyHeaderIntField(offset_magic, 0x00000000);
|
||||
modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
|
||||
output = TestCommon.execCommon(execArgs);
|
||||
output.shouldContain("The shared archive file has a bad magic number");
|
||||
output.shouldNotContain("Checksum verification failed");
|
||||
|
||||
copyFile(orgJsaFile, jsa);
|
||||
// modify _version and _paths_misc_info_size, test should fail
|
||||
System.out.println("\n2d. Corrupt _version and _paths_misc_info_size, should fail\n");
|
||||
// modify _version, test should fail
|
||||
System.out.println("\n2d. Corrupt _version, should fail\n");
|
||||
modifyHeaderIntField(offset_version, 0x00000000);
|
||||
modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
|
||||
output = TestCommon.execCommon(execArgs);
|
||||
output.shouldContain("The shared archive file has the wrong version");
|
||||
output.shouldNotContain("Checksum verification failed");
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary ensure -XX:+TraceClassPaths showing entire expecting app classpath
|
||||
* @summary ensure -Xlog:class+path showing entire expecting app classpath
|
||||
* @requires vm.cds
|
||||
* @library /test/lib
|
||||
* @modules jdk.jartool/sun.tools.jar
|
||||
@ -85,22 +85,23 @@ public class TraceLongClasspath {
|
||||
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps +
|
||||
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar";
|
||||
|
||||
String myCP = longClassPath + ps + appJar;
|
||||
String dumpCP = longClassPath + ps + appJar;
|
||||
// Dump an archive with a specified JAR file in -classpath
|
||||
TestCommon.testDump(myCP, TestCommon.list("Hello"));
|
||||
TestCommon.testDump(dumpCP, TestCommon.list("Hello"));
|
||||
|
||||
// Then try to execute the archive with a different classpath and with -XX:+TraceClassPaths.
|
||||
// The diagnosis "expecting" app classpath trace should show the entire classpath.
|
||||
// Then try to execute the archive with a different classpath and with -Xlog:class+path.
|
||||
// The diagnostic "expecting" app classpath trace should show the entire classpath (excluding any non-existent dump-time paths).
|
||||
String recordedCP = dummyJar + ps + appJar;
|
||||
TestCommon.run(
|
||||
"-XX:+TraceClassPaths", "-Xlog:cds",
|
||||
"-Xlog:class+path", "-Xlog:cds",
|
||||
"-cp", appJar,
|
||||
"Hello")
|
||||
.assertAbnormalExit(output -> {
|
||||
output.shouldContain("Unable to use shared archive");
|
||||
output.shouldContain("shared class paths mismatch");
|
||||
// the "expecting" app classpath from -XX:+TraceClassPaths should not
|
||||
// the "expecting" app classpath from -Xlog:class+path should not
|
||||
// be truncated
|
||||
output.shouldContain(myCP);
|
||||
output.shouldContain(recordedCP);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
public class CpAttr6 {
|
||||
public static void main(String args[]) {
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user