--- a/src/hotspot/share/classfile/classLoader.cpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/classfile/classLoader.cpp Tue Aug 27 22:14:52 2019 -0700
@@ -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::_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 @@
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 @@
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 @@
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 @@
} 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 @@
}
return true;
} else {
-#if INCLUDE_CDS
- if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
- _shared_paths_misc_info->add_nonexist_path(path);
- }
-#endif
return false;
}
}
@@ -1567,12 +1534,6 @@
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_shared_path() {
if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
ClassLoaderExt::setup_search_paths();
- _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
}
}
--- a/src/hotspot/share/classfile/classLoader.hpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/classfile/classLoader.hpp Tue Aug 27 22:14:52 2019 -0700
@@ -47,17 +47,19 @@
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 @@
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 @@
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 @@
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 @@
void add_to_list(ClassPathEntry* new_entry);
};
-class SharedPathsMiscInfo;
-
class ClassLoader: AllStatic {
public:
enum ClassLoaderType {
@@ -230,8 +221,6 @@
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 @@
}
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);
--- a/src/hotspot/share/classfile/classLoaderExt.cpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp Tue Aug 27 22:14:52 2019 -0700
@@ -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 @@
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 @@
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::setup_search_paths() {
- shared_paths_misc_info()->record_app_offset();
ClassLoaderExt::setup_app_search_path();
}
@@ -248,12 +249,6 @@
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.
--- a/src/hotspot/share/classfile/classLoaderExt.hpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/classfile/classLoaderExt.hpp Tue Aug 27 22:14:52 2019 -0700
@@ -47,9 +47,6 @@
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 @@
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; }
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp Tue Aug 27 22:14:15 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp Tue Aug 27 22:14:15 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/src/hotspot/share/include/cds.h Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/include/cds.h Tue Aug 27 22:14:52 2019 -0700
@@ -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 {
--- a/src/hotspot/share/memory/filemap.cpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/memory/filemap.cpp Tue Aug 27 22:14:52 2019 -0700
@@ -241,7 +241,6 @@
// 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 @@
_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 @@
FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
}
- size_t len = strlen(cpe->name()) + 1;
+ // 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);
+}
+
+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(), cpe->name());
+ strcpy(_name->data(), name);
}
-bool SharedClassPathEntry::validate(bool is_class_path) {
+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 @@
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::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 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 @@
// 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);
}
- 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();
+ if (is_jrt) {
+ cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
+ } else {
+ cpe = cpe->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::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 @@
}
};
-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 @@
// 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 @@
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 @@
}
}
+ 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 @@
}
}
+ validate_non_existent_class_paths();
+
_validating_shared_path_table = false;
#if INCLUDE_JVMTI
@@ -771,6 +833,26 @@
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 @@
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 @@
}
}
- _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 @@
// 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 @@
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 @@
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 @@
//
// 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 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* 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);
--- a/src/hotspot/share/memory/filemap.hpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/memory/filemap.hpp Tue Aug 27 22:14:52 2019 -0700
@@ -49,8 +49,12 @@
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 @@
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 @@
void set_manifest(Array<u1>* manifest) {
_manifest = manifest;
}
+ bool check_non_existent() const;
};
struct ArchiveHeapOopmapInfo {
@@ -147,30 +153,12 @@
// 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 @@
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 @@
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 @@
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);
--- a/src/hotspot/share/prims/cdsoffsets.cpp Tue Aug 27 22:14:15 2019 -0700
+++ b/src/hotspot/share/prims/cdsoffsets.cpp Tue Aug 27 22:14:52 2019 -0700
@@ -53,7 +53,6 @@
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));
--- a/test/hotspot/jtreg/runtime/cds/appcds/AppendClasspath.java Tue Aug 27 22:14:15 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/AppendClasspath.java Tue Aug 27 22:14:52 2019 -0700
@@ -95,19 +95,5 @@
"-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);
-
}
}
--- a/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java Tue Aug 27 22:14:15 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java Tue Aug 27 22:14:52 2019 -0700
@@ -42,6 +42,11 @@
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 @@
}
}
+ 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) { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java Tue Aug 27 22:14:52 2019 -0700
@@ -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);
+ }
+}
--- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java Tue Aug 27 22:14:15 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java Tue Aug 27 22:14:52 2019 -0700
@@ -61,7 +61,6 @@
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 @@
// 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 @@
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 @@
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");
--- a/test/hotspot/jtreg/runtime/cds/appcds/TraceLongClasspath.java Tue Aug 27 22:14:15 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/TraceLongClasspath.java Tue Aug 27 22:14:52 2019 -0700
@@ -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 @@
"/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);
});
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/CpAttr6.java Tue Aug 27 22:14:52 2019 -0700
@@ -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");
+ }
+}