代码拉取完成,页面将自动刷新
同步操作将从 misaka00251/openjdk-1.8.0 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 49f7ef8df4cade226de5754172e208975343967c Mon Sep 17 00:00:00 2001
Date: Sat, 3 Sep 2022 14:25:50 +0000
Subject: 8202951-Support-default-jsa
---
common/autoconf/configure.ac | 3 +
common/autoconf/generated-configure.sh | 40 +++++
common/autoconf/jdk-options.m4 | 32 ++++
common/autoconf/spec.gmk.in | 4 +
common/bin/compare.sh | 1 +
hotspot/src/share/vm/cds/archiveBuilder.cpp | 34 +++-
hotspot/src/share/vm/cds/archiveBuilder.hpp | 4 +
hotspot/src/share/vm/cds/dynamicArchive.cpp | 1 +
.../src/share/vm/classfile/classLoader.cpp | 152 +++++++++++++++++-
.../src/share/vm/classfile/classLoader.hpp | 15 +-
.../share/vm/classfile/classLoaderData.hpp | 1 +
hotspot/src/share/vm/classfile/dictionary.cpp | 2 +-
.../vm/classfile/sharedPathsMiscInfo.hpp | 13 +-
.../vm/classfile/systemDictionaryShared.cpp | 2 +-
hotspot/src/share/vm/memory/filemap.cpp | 34 +++-
hotspot/src/share/vm/memory/filemap.hpp | 7 +
hotspot/src/share/vm/memory/metachunk.hpp | 2 +
hotspot/src/share/vm/memory/metaspace.cpp | 14 ++
hotspot/src/share/vm/memory/metaspace.hpp | 2 +
.../src/share/vm/memory/metaspaceShared.cpp | 22 +++
.../src/share/vm/memory/metaspaceShared.hpp | 5 +-
hotspot/src/share/vm/oops/instanceKlass.cpp | 5 +-
hotspot/src/share/vm/runtime/arguments.cpp | 34 ++--
hotspot/src/share/vm/runtime/arguments.hpp | 6 +
hotspot/src/share/vm/utilities/hashtable.cpp | 1 +
hotspot/test/runtime/appcds/TestCommon.java | 74 ++++++++-
.../appcds/dynamicArchive/DynamicFlag.java | 39 +++++
.../dynamicArchive/DynamicHelloTest.java | 42 +++++
.../VerifyWithDynamicArchive.java | 42 +++++
jdk/make/BuildJdk.gmk | 7 +
30 files changed, 603 insertions(+), 37 deletions(-)
create mode 100644 hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java
create mode 100644 hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java
create mode 100644 hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java
diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac
index 151e5a10..dbcdd59e 100644
--- a/common/autoconf/configure.ac
+++ b/common/autoconf/configure.ac
@@ -98,6 +98,9 @@ JDKOPT_SETUP_JVM_INTERPRETER
JDKOPT_SETUP_JVM_VARIANTS
JDKOPT_SETUP_DEBUG_LEVEL
+# Enable default CDS ARCHIVE
+JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE
+
# With basic setup done, call the custom early hook.
CUSTOM_EARLY_HOOK
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index c41c4336..f0e49f50 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -883,6 +883,7 @@ OUTPUT_ROOT
CONF_NAME
SPEC
DEVKIT_LIB_DIR
+BUILD_CDS_ARCHIVE
BUILD_VARIANT_RELEASE
DEBUG_CLASSFILES
FASTDEBUG
@@ -1047,6 +1048,7 @@ with_jvm_interpreter
with_jvm_variants
enable_debug
with_debug_level
+enable_cds_archive
with_devkit
with_sys_root
with_sysroot
@@ -1857,6 +1859,8 @@ Optional Features:
[disabled]
--enable-debug set the debug level to fastdebug (shorthand for
--with-debug-level=fastdebug) [disabled]
+ --disable-cds-archive Set to disable generation of a default CDS archive
+ in the product image [enabled]
--disable-headful disable building headful support (graphical UI
support) [enabled]
--enable-hotspot-test-in-build
@@ -14704,6 +14708,42 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEBUG_LEVEL" >&5
$as_echo "$DEBUG_LEVEL" >&6; }
+
+
+# Enable default CDS ARCHIVE
+
+ # Check whether --enable-cds-archive was given.
+if test "${enable_cds_archive+set}" = set; then :
+ enableval=$enable_cds_archive;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if a default CDS archive should be generated" >&5
+$as_echo_n "checking if a default CDS archive should be generated... " >&6; }
+ if test "x$COMPILE_TYPE" = "xcross"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, not possible with cross compilation" >&5
+$as_echo "no, not possible with cross compilation" >&6; }
+ BUILD_CDS_ARCHIVE="false"
+ elif test "x$enable_cds_archive" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5
+$as_echo "yes, forced" >&6; }
+ BUILD_CDS_ARCHIVE="true"
+ elif test "x$enable_cds_archive" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ BUILD_CDS_ARCHIVE="true"
+ elif test "x$enable_cds_archive" = "xno"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5
+$as_echo "no, forced" >&6; }
+ BUILD_CDS_ARCHIVE="false"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "--enable-cds_archive can only be yes/no or empty" "$LINENO" 5
+ fi
+
+
+
if test "x$DEBUG_LEVEL" != xrelease && \
test "x$DEBUG_LEVEL" != xfastdebug && \
test "x$DEBUG_LEVEL" != xslowdebug; then
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index bca78afe..c506086d 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -789,6 +789,38 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
AC_SUBST(ZIP_DEBUGINFO_FILES)
])
+################################################################################
+#
+# Disable the default CDS archive generation
+# cross compilation - disabled
+#
+AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE],
+[
+ AC_ARG_ENABLE([cds-archive], [AS_HELP_STRING([--disable-cds-archive],
+ [Set to disable generation of a default CDS archive in the product image @<:@enabled@:>@])])
+
+ AC_MSG_CHECKING([if a default CDS archive should be generated])
+ if test "x$COMPILE_TYPE" = "xcross"; then
+ AC_MSG_RESULT([no, not possible with cross compilation])
+ BUILD_CDS_ARCHIVE="false"
+ elif test "x$enable_cds_archive" = "xyes"; then
+ AC_MSG_RESULT([yes, forced])
+ BUILD_CDS_ARCHIVE="true"
+ elif test "x$enable_cds_archive" = "x"; then
+ AC_MSG_RESULT([yes])
+ BUILD_CDS_ARCHIVE="true"
+ elif test "x$enable_cds_archive" = "xno"; then
+ AC_MSG_RESULT([no, forced])
+ BUILD_CDS_ARCHIVE="false"
+ else
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([--enable-cds_archive can only be yes/no or empty])
+ fi
+
+ AC_SUBST(BUILD_CDS_ARCHIVE)
+])
+
+
# Support for customization of the build process. Some build files
# will include counterparts from this location, if they exist. This allows
# for a degree of customization of the build targets and the rules/recipes
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 4c3a9f61..79248cbf 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -612,6 +612,10 @@ LIBZIP_CAN_USE_MMAP:=@LIBZIP_CAN_USE_MMAP@
VCRUNTIME_1_DLL:=@VCRUNTIME_1_DLL@
MSVCP_DLL:=@MSVCP_DLL@
UCRT_DLL_DIR:=@UCRT_DLL_DIR@
+# CDS_ARCHIVE
+BUILD_CDS_ARCHIVE:=@BUILD_CDS_ARCHIVE@
+
+
# ADD_SRCS takes a single argument with source roots
diff --git a/common/bin/compare.sh b/common/bin/compare.sh
index ff88bb1f..a36464a9 100644
--- a/common/bin/compare.sh
+++ b/common/bin/compare.sh
@@ -290,6 +290,7 @@ compare_general_files() {
! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \
+ ! -name "classes.jsa" \
| $GREP -v "./bin/" | $SORT | $FILTER)
echo General files...
diff --git a/hotspot/src/share/vm/cds/archiveBuilder.cpp b/hotspot/src/share/vm/cds/archiveBuilder.cpp
index 144dedfa..13a62002 100644
--- a/hotspot/src/share/vm/cds/archiveBuilder.cpp
+++ b/hotspot/src/share/vm/cds/archiveBuilder.cpp
@@ -59,6 +59,18 @@ ArchiveBuilder::SourceObjList::~SourceObjList() {
delete _objs;
}
+static void caculate_fingerprint(Klass * klass) {
+ if (klass->oop_is_instance()) {
+ InstanceKlass* ik = InstanceKlass::cast(klass);
+ for (int i = 0; i < ik->methods()->length(); i++) {
+ Method* m = ik->methods()->at(i);
+ Fingerprinter fp(m);
+ // The side effect of this call sets method's fingerprint field.
+ fp.fingerprint();
+ }
+ }
+}
+
void ArchiveBuilder::SourceObjList::append(MetaspaceClosure::Ref* enclosing_ref, SourceObjInfo* src_info) {
// Save this source object for copying
_objs->append(src_info);
@@ -166,6 +178,7 @@ ArchiveBuilder::ArchiveBuilder() :
_buffer_to_requested_delta(0),
_rw_region("rw", MAX_SHARED_DELTA),
_ro_region("ro", MAX_SHARED_DELTA),
+ _md_region("md", MAX_SHARED_DELTA),
_rw_src_objs(),
_ro_src_objs(),
_src_obj_table(INITIAL_TABLE_SIZE),
@@ -384,6 +397,7 @@ bool ArchiveBuilder::gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool re
Klass* klass = (Klass*)ref->obj();
assert(klass->is_klass(), "must be");
if (!is_excluded(klass)) {
+ caculate_fingerprint(klass);
_klasses->append(klass);
if (klass->oop_is_instance()) {
_num_instance_klasses ++;
@@ -434,7 +448,8 @@ size_t ArchiveBuilder::estimate_archive_size() {
address ArchiveBuilder::reserve_buffer() {
size_t buffer_size = estimate_archive_size();
- ReservedSpace rs(buffer_size, os::vm_allocation_granularity(), false);
+ size_t package_hash_table_est = align_up(ClassLoader::estimate_size_for_archive(), (size_t)os::vm_allocation_granularity());
+ ReservedSpace rs(buffer_size + package_hash_table_est, os::vm_allocation_granularity(), false);
if (!rs.is_reserved()) {
tty->print_cr("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size);
vm_direct_exit(0);
@@ -443,7 +458,8 @@ address ArchiveBuilder::reserve_buffer() {
// buffer_bottom is the lowest address of the 2 core regions (rw, ro) when
// we are copying the class metadata into the buffer.
address buffer_bottom = (address)rs.base();
- _shared_rs = rs;
+ _shared_rs = rs.first_part(buffer_size);
+ _md_rs = rs.last_part(buffer_size);
_buffer_bottom = buffer_bottom;
_last_verified_top = buffer_bottom;
@@ -508,6 +524,19 @@ void ArchiveBuilder::dump_ro_metadata() {
make_shallow_copies(&_ro_region, &_ro_src_objs);
}
+void ArchiveBuilder::dump_md_metadata() {
+ ResourceMark rm;
+ if (InfoDynamicCDS) {
+ dynamic_cds_log->print_cr("Allocating MD objects ... ");
+ }
+ _current_dump_space = &_md_region;
+ _md_region.init(&_md_rs, &_md_vs);
+ char* md_top = _md_vs.low();
+ char* md_end = _md_vs.high_boundary();
+ _md_region.allocate(md_end - md_top);
+ ClassLoader::serialize_package_hash_table(&md_top, md_end);
+}
+
void ArchiveBuilder::start_dump_space(DumpRegion* next) {
address bottom = _last_verified_top;
address top = (address)(_current_dump_space->top());
@@ -749,6 +778,7 @@ void ArchiveBuilder::write_archive(FileMapInfo* mapinfo) {
write_region(mapinfo, MetaspaceShared::d_rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
write_region(mapinfo, MetaspaceShared::d_ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
+ write_region(mapinfo, MetaspaceShared::d_md, &_md_region, /*read_only=*/true, /*allow_exec=*/false);
char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap());
diff --git a/hotspot/src/share/vm/cds/archiveBuilder.hpp b/hotspot/src/share/vm/cds/archiveBuilder.hpp
index 18cd3c62..f7a5c107 100644
--- a/hotspot/src/share/vm/cds/archiveBuilder.hpp
+++ b/hotspot/src/share/vm/cds/archiveBuilder.hpp
@@ -163,10 +163,13 @@ private:
static const int MAX_TABLE_SIZE = 1000000;
ReservedSpace _shared_rs;
+ ReservedSpace _md_rs;
VirtualSpace _shared_vs;
+ VirtualSpace _md_vs;
DumpRegion _rw_region;
DumpRegion _ro_region;
+ DumpRegion _md_region;
BitMap _ptrmap;
SourceObjList _rw_src_objs; // objs to put in rw region
@@ -327,6 +330,7 @@ public:
void dump_rw_metadata();
void dump_ro_metadata();
+ void dump_md_metadata();
void relocate_metaspaceobj_embedded_pointers();
void relocate_roots();
void make_klasses_shareable();
diff --git a/hotspot/src/share/vm/cds/dynamicArchive.cpp b/hotspot/src/share/vm/cds/dynamicArchive.cpp
index efed275c..a623c5b0 100644
--- a/hotspot/src/share/vm/cds/dynamicArchive.cpp
+++ b/hotspot/src/share/vm/cds/dynamicArchive.cpp
@@ -149,6 +149,7 @@ public:
relocate_to_requested();
+ dump_md_metadata();
write_archive(serialized_data);
release_header();
diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp
index e3470ca8..04fa84d4 100644
--- a/hotspot/src/share/vm/classfile/classLoader.cpp
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp
@@ -219,6 +219,30 @@ const char* ClassLoader::package_from_name(const char* const class_name, bool* b
return (const char *)pkg_name;
}
+const char* ClassLoader::get_file_name_from_path(const char* path) {
+ const char* pos = strrchr(path, '/');
+ if (pos == NULL) {
+ return path;
+ } else {
+ return pos + 1;
+ }
+}
+
+const char* ClassLoader::get_boot_class_path(const char* shared_path) {
+ const char* shared_name = get_file_name_from_path(shared_path);
+ ClassPathEntry* e = _first_entry;
+ while (e != NULL) {
+ if (e->sys_class()) {
+ const char* name = get_file_name_from_path(e->name());
+ if (strcmp(name, shared_name) == 0) {
+ return e->name();
+ }
+ }
+ e = e->next();
+ }
+ return NULL;
+}
+
MetaIndex::MetaIndex(char** meta_package_names, int num_meta_package_names) {
if (num_meta_package_names == 0) {
_meta_package_names = NULL;
@@ -512,6 +536,8 @@ void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta
int line_no = 0;
#if INCLUDE_CDS
if (DumpSharedSpaces) {
+ meta_index_path = Arguments::get_is_default_jsa() ?
+ get_file_name_from_path(meta_index_path) : meta_index_path;
if (file != NULL) {
_shared_paths_misc_info->add_required_file(meta_index_path);
} else {
@@ -644,7 +670,9 @@ void ClassLoader::setup_bootstrap_search_path() {
}
#if INCLUDE_CDS
if (DumpSharedSpaces) {
- _shared_paths_misc_info->add_boot_classpath(sys_class_path);
+ const char* new_sys_class_path = Arguments::get_is_default_jsa() ?
+ get_file_name_from_path(sys_class_path) : sys_class_path;
+ _shared_paths_misc_info->add_boot_classpath(new_sys_class_path);
}
#endif
setup_search_path(sys_class_path);
@@ -688,7 +716,7 @@ void ClassLoader::setup_search_path(const char *class_path, bool canonicalize) {
path = canonical_path;
}
}
- update_class_path_entry_list(path, /*check_for_duplicates=*/canonicalize);
+ update_class_path_entry_list(path, /*check_for_duplicates=*/canonicalize, true, true);
#if INCLUDE_CDS
if (DumpSharedSpaces) {
check_shared_classpath(path);
@@ -816,7 +844,9 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) {
// Returns true IFF the file/dir exists and the entry was successfully created.
bool ClassLoader::update_class_path_entry_list(const char *path,
bool check_for_duplicates,
- bool throw_exception) {
+ bool throw_exception,
+ bool sys_class_type) {
+ // sys_class_type indicates whether *path is a system path. The default value is false.
struct stat st;
if (os::stat(path, &st) == 0) {
// File or directory found
@@ -826,6 +856,11 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
if (new_entry == NULL) {
return false;
}
+ // If the path is a system path, set sys_class of the newly created
+ // linked list node to true. The default value is false.
+ if (sys_class_type) {
+ new_entry->set_sys_class(true);
+ }
// The kernel VM adds dynamically to the end of the classloader path and
// doesn't reorder the bootclasspath which would break java.lang.Package
// (see PackageInfo).
@@ -837,6 +872,8 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
} else {
#if INCLUDE_CDS
if (DumpSharedSpaces) {
+ path = Arguments::get_is_default_jsa() ?
+ get_file_name_from_path(path) : path;
_shared_paths_misc_info->add_nonexist_path(path);
}
#endif
@@ -918,6 +955,7 @@ int ClassLoader::crc32(int crc, const char* buf, int len) {
class PackageInfo: public BasicHashtableEntry<mtClass> {
public:
const char* _pkgname; // Package name
+ const char* _filename; // File name
int _classpath_index; // Index of directory or JAR file loaded from
PackageInfo* next() {
@@ -926,9 +964,10 @@ public:
const char* pkgname() { return _pkgname; }
void set_pkgname(char* pkgname) { _pkgname = pkgname; }
+ void set_filename(char* filename) { _filename = filename; }
const char* filename() {
- return ClassLoader::classpath_entry(_classpath_index)->name();
+ return _filename == NULL ? ClassLoader::classpath_entry(_classpath_index)->name() : _filename;
}
void set_index(int index) {
@@ -975,11 +1014,12 @@ public:
return get_entry(hash_to_index(hash), hash, pkgname, n);
}
- PackageInfo* new_entry(char* pkgname, int n) {
+ PackageInfo* new_entry(char* pkgname, int n, char* filename = NULL) {
unsigned int hash = compute_hash(pkgname, n);
PackageInfo* pp;
pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
pp->set_pkgname(pkgname);
+ pp->set_filename(filename);
return pp;
}
@@ -999,6 +1039,9 @@ public:
}
CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
+ CDS_ONLY(void serialize(char** top, char* end);)
+ CDS_ONLY(void deserialize(char* start);)
+ CDS_ONLY(size_t estimate_size();)
};
#if INCLUDE_CDS
@@ -1035,6 +1078,93 @@ void PackageHashtable::copy_table(char** top, char* end,
*tableSize = len;
}
+size_t PackageHashtable::estimate_size() {
+ int size = sizeof(int);
+ ClassPathEntry* e = ClassLoader::_first_entry;
+ while (e != NULL) {
+ int length = (int)(strlen(e->name()) + 1);
+ size += length;
+ e = e->next();
+ }
+ size = align_size_up(size, sizeof(int));
+
+ size += sizeof(int);
+ for (int i = 0; i < table_size(); ++i) {
+ for (PackageInfo* pp = bucket(i);
+ pp != NULL;
+ pp = pp->next()) {
+ size += sizeof(int);
+ int n1 = (int)(strlen(pp->pkgname()) + 1);
+ n1 = align_size_up(n1, sizeof(int));
+ size += n1;
+ }
+ }
+ return align_size_up(size, sizeof(int));
+}
+
+void PackageHashtable::serialize(char** top, char* end) {
+ *(int*)(*top) = ClassLoader::_num_entries;
+ *top += sizeof(int);
+
+ ClassPathEntry* e = ClassLoader::_first_entry;
+ while (e != NULL) {
+ int length = (int)(strlen(e->name()) + 1);
+ memcpy(*top, e->name(), length);
+ *top += length;
+ e = e->next();
+ }
+ *top = (char*)align_size_up((intptr_t)*top, sizeof(int));
+ *(int*)(*top) = number_of_entries();
+ *top += sizeof(int);
+
+ for (int i = 0; i < table_size(); ++i) {
+ for (PackageInfo* pp = bucket(i);
+ pp != NULL;
+ pp = pp->next()) {
+ *(int*)(*top) = pp->_classpath_index;
+ *top += sizeof(int);
+ int n1 = (int)(strlen(pp->pkgname()) + 1);
+ memcpy(*top, pp->pkgname(), n1);
+ n1 = align_size_up(n1, sizeof(int));
+ *top += n1;
+ }
+ }
+}
+
+void PackageHashtable::deserialize(char* start) {
+ int num_entries = *(int*)start;
+ char** class_loader_entries = NEW_C_HEAP_ARRAY(char*, num_entries, mtClass);
+ start += sizeof(int);
+ int entries_len = 0;
+ for (int i = 0, index = 0; i < num_entries; i++) {
+ class_loader_entries[index++] = start + entries_len;
+ entries_len += (int)(strlen(start + entries_len) + 1);
+ }
+ start += align_size_up(entries_len, sizeof(int));
+ int number_of_entries = *(int*)start;
+ start += sizeof(int);
+ for (int i = 0; i < number_of_entries; i++) {
+ int classpath_index = *(int*)start;
+ start += sizeof(int);
+ char* pkgname = start;
+ const char *cp = strrchr(pkgname, '/');
+ if (cp != NULL) {
+ int n = cp - pkgname + 1;
+ if (get_entry(pkgname, n) == NULL) {
+ PackageInfo* info = new_entry(pkgname, n, class_loader_entries[classpath_index]);
+ add_entry(info);
+ }
+ }
+ int n1 = (int)(strlen(start) + 1);
+ start += align_size_up(n1, sizeof(int));
+ }
+ FREE_C_HEAP_ARRAY(char*, class_loader_entries, mtClass);
+}
+
+void ClassLoader::deserialize_package_hash_table(char* start) {
+ assert(_package_hash_table != NULL, "should have one yet");
+ _package_hash_table->deserialize(start);
+}
void ClassLoader::copy_package_info_buckets(char** top, char* end) {
_package_hash_table->copy_buckets(top, end);
@@ -1043,6 +1173,14 @@ void ClassLoader::copy_package_info_buckets(char** top, char* end) {
void ClassLoader::copy_package_info_table(char** top, char* end) {
_package_hash_table->copy_table(top, end, _package_hash_table);
}
+
+size_t ClassLoader::estimate_size_for_archive() {
+ return _package_hash_table->estimate_size();
+}
+
+void ClassLoader::serialize_package_hash_table(char** top, char* end) {
+ return _package_hash_table->serialize(top, end);
+}
#endif
PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
@@ -1226,8 +1364,8 @@ void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int len
void ClassLoader::create_package_info_table() {
- assert(_package_hash_table == NULL, "shouldn't have one yet");
- _package_hash_table = new PackageHashtable(package_hash_table_size);
+ assert(_package_hash_table == NULL, "shouldn't have one yet");
+ _package_hash_table = new PackageHashtable(package_hash_table_size);
}
diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp
index 9514d3bb..cf39ce99 100644
--- a/hotspot/src/share/vm/classfile/classLoader.hpp
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp
@@ -49,13 +49,18 @@ class MetaIndex: public CHeapObj<mtClass> {
class ClassPathEntry: public CHeapObj<mtClass> {
private:
ClassPathEntry* _next;
+ bool _sys_class;
public:
// Next entry in class path
ClassPathEntry* next() { return _next; }
+ bool sys_class() const { return _sys_class; }
void set_next(ClassPathEntry* next) {
// may have unlocked readers, so write atomically.
OrderAccess::release_store_ptr(&_next, next);
}
+ void set_sys_class(bool isSysClass) {
+ _sys_class = isSysClass;
+ }
virtual bool is_jar_file() = 0;
virtual const char* name() = 0;
virtual bool is_lazy();
@@ -158,6 +163,7 @@ class ClassLoader: AllStatic {
};
protected:
friend class LazyClassPathEntry;
+ friend class PackageHashtable;
// Performance counters
static PerfCounter* _perf_accumulated_time;
@@ -234,7 +240,8 @@ class ClassLoader: AllStatic {
static int crc32(int crc, const char* buf, int len);
static bool update_class_path_entry_list(const char *path,
bool check_for_duplicates,
- bool throw_exception=true);
+ bool throw_exception=true,
+ bool sys_class=false);
static void print_bootclasspath();
// Timing
@@ -318,6 +325,9 @@ class ClassLoader: AllStatic {
// Initialization
static void initialize();
CDS_ONLY(static void initialize_shared_path();)
+ static const char* get_file_name_from_path(const char* path);
+ static const char* get_boot_class_path(const char* shared_path);
+
static void create_package_info_table();
static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
int number_of_entries);
@@ -340,6 +350,9 @@ class ClassLoader: AllStatic {
// Sharing dump and restore
static void copy_package_info_buckets(char** top, char* end);
static void copy_package_info_table(char** top, char* end);
+ static size_t estimate_size_for_archive();
+ static void serialize_package_hash_table(char** top, char* end);
+ static void deserialize_package_hash_table(char* start);
static void check_shared_classpath(const char *path);
static void finalize_shared_paths_misc_info();
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index 9b901303..7155257e 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -168,6 +168,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
friend class ClassLoaderDataGraphMetaspaceIterator;
friend class MetaDataFactory;
friend class Method;
+ friend class VM_PopulateDumpSharedSpace;
static ClassLoaderData * _the_null_class_loader_data;
diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp
index b9d473b0..d41372ec 100644
--- a/hotspot/src/share/vm/classfile/dictionary.cpp
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp
@@ -197,7 +197,7 @@ void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
}
void Dictionary::remove_classes_in_error_state() {
- assert(DumpSharedSpaces, "supported only when dumping");
+ assert(DynamicDumpSharedSpaces || DumpSharedSpaces, "supported only when dumping");
DictionaryEntry* probe = NULL;
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
index 882fed01..b1609e46 100644
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
@@ -26,6 +26,7 @@
#define SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
#include "runtime/os.hpp"
+#include "runtime/arguments.hpp"
// 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_entry.
@@ -111,12 +112,18 @@ public:
add_path(path, REQUIRED);
struct stat st;
- if (os::stat(path, &st) != 0) {
+ if (!Arguments::get_is_default_jsa() && os::stat(path, &st) != 0) {
assert(0, "sanity");
ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
}
- write_time(st.st_mtime);
- write_long(st.st_size);
+
+ if (Arguments::get_is_default_jsa()) {
+ write_time(0);
+ write_long(0);
+ } else {
+ write_time(st.st_mtime);
+ write_long(st.st_size);
+ }
}
// The path must exist, and must contain exactly <num_entries> files/dirs
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
index 99354cd4..3a601ee3 100644
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
@@ -659,7 +659,7 @@ bool SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason)
bool SystemDictionaryShared::is_jfr_event_class(InstanceKlass *k) {
while (k) {
- if (k->name()->equals("jdk/jfr/Event")) {
+ if (k->name()->equals("jdk/jfr/Event") || k->name()->starts_with("jdk/jfr/event")) {
return true;
}
k = k->java_super();
diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp
index 3f410647..5fd62a74 100644
--- a/hotspot/src/share/vm/memory/filemap.cpp
+++ b/hotspot/src/share/vm/memory/filemap.cpp
@@ -263,7 +263,12 @@ void FileMapInfo::allocate_classpath_entry_table() {
for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) {
const char *name = cpe->name();
- int name_bytes = (int)(strlen(name) + 1);
+ int name_bytes;
+ if (cpe->sys_class()) {
+ name_bytes = (int)(strlen(ClassLoader::get_file_name_from_path(name)) + 1);
+ } else {
+ name_bytes = (int)(strlen(name) + 1);
+ }
if (pass == 0) {
count ++;
@@ -286,7 +291,13 @@ void FileMapInfo::allocate_classpath_entry_table() {
}
EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
- SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
+ if (cpe->sys_class()) {
+ // Jdk boot jar not need validate timestamp for we may copy whole jdk.
+ SharedClassUtil::update_shared_classpath(cpe, ent, 0, st.st_size, THREAD);
+ ent->set_sys_class(true);
+ } else {
+ SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
+ }
} else {
ent->_filesize = -1;
if (!os::dir_is_empty(name)) {
@@ -295,7 +306,11 @@ void FileMapInfo::allocate_classpath_entry_table() {
}
ent->_name = strptr;
if (strptr + name_bytes <= strptr_max) {
- strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0.
+ if (cpe->sys_class()) {
+ strncpy(strptr, ClassLoader::get_file_name_from_path(name), (size_t)name_bytes);
+ } else {
+ strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0.
+ }
strptr += name_bytes;
} else {
assert(0, "miscalculated buffer size");
@@ -334,6 +349,14 @@ bool FileMapInfo::validate_classpath_entry_table() {
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
tty->print_cr("[Checking shared classpath entry: %s]", name);
}
+ if (ent->_sys_class) {
+ name = ClassLoader::get_boot_class_path(name);
+ if (name == NULL) {
+ fail_continue("Required classpath entry of system class does not exist");
+ continue;
+ }
+ }
+
if (os::stat(name, &st) != 0) {
fail_continue("Required classpath entry does not exist: %s", name);
ok = false;
@@ -343,7 +366,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
ok = false;
}
} else {
- if (ent->_timestamp != st.st_mtime ||
+ if ((ent->_timestamp != 0 && ent->_timestamp != st.st_mtime) ||
ent->_filesize != st.st_size) {
ok = false;
if (PrintSharedArchiveAndExit) {
@@ -640,6 +663,7 @@ void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) {
size_t used = space->used_bytes_slow(Metaspace::NonClassType);
size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType);
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
+ space->reset_metachunks();
write_region(i, (char*)space->bottom(), used, capacity, read_only, false);
}
@@ -967,7 +991,7 @@ bool FileMapInfo::validate_header() {
return DynamicArchive::validate(this);
}
- if (status) {
+ if (status && !_header->_is_default_jsa) {
if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) {
if (!PrintSharedArchiveAndExit) {
fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)");
diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp
index eab9ebcf..36b27f13 100644
--- a/hotspot/src/share/vm/memory/filemap.hpp
+++ b/hotspot/src/share/vm/memory/filemap.hpp
@@ -52,9 +52,13 @@ public:
const char *_name;
time_t _timestamp; // jar timestamp, 0 if is directory
long _filesize; // jar file size, -1 if is directory
+ bool _sys_class;
bool is_dir() {
return _filesize == -1;
}
+ void set_sys_class(bool isSysClass) {
+ _sys_class = isSysClass;
+ }
};
class FileMapInfo : public CHeapObj<mtInternal> {
@@ -100,6 +104,7 @@ public:
int _version; // (from enum, above.)
size_t _alignment; // how shared archive should be aligned
int _obj_alignment; // value of ObjectAlignmentInBytes
+ bool _is_default_jsa; // indicates whether is the default jsa file
struct space_info {
int _crc; // crc checksum of the current space
@@ -264,6 +269,8 @@ public:
bool is_open() { return _file_open; }
bool is_static() const { return _is_static; }
bool is_mapped() const { return _is_mapped; }
+ bool is_default_jsa() const { return _header->_is_default_jsa; }
+ void set_is_default_jsa(bool v) { _header->_is_default_jsa = v; }
void set_is_mapped(bool v) { _is_mapped = v; }
ReservedSpace reserve_shared_memory();
void set_requested_base(char* b) { dynamic_header()->set_requested_base(b); }
diff --git a/hotspot/src/share/vm/memory/metachunk.hpp b/hotspot/src/share/vm/memory/metachunk.hpp
index e873dc6a..7889b622 100644
--- a/hotspot/src/share/vm/memory/metachunk.hpp
+++ b/hotspot/src/share/vm/memory/metachunk.hpp
@@ -126,6 +126,8 @@ class Metachunk : public Metabase<Metachunk> {
VirtualSpaceNode* container() const { return _container; }
+ void reset_container() { _container = NULL; }
+
MetaWord* bottom() const { return (MetaWord*) this; }
// Reset top to bottom so chunk can be reused.
diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp
index 7e95b5c0..6c4654b2 100644
--- a/hotspot/src/share/vm/memory/metaspace.cpp
+++ b/hotspot/src/share/vm/memory/metaspace.cpp
@@ -775,6 +775,7 @@ class SpaceManager : public CHeapObj<mtClass> {
// Notify memory usage to MemoryService.
void track_metaspace_memory_usage();
+ void reset_metachunks();
// debugging support.
void dump(outputStream* const out) const;
@@ -1923,6 +1924,15 @@ void ChunkManager::print_on(outputStream* out) const {
// SpaceManager methods
+void SpaceManager::reset_metachunks() {
+ for (ChunkIndex i = ZeroIndex; i <= HumongousIndex; i = next_chunk_index(i)) {
+ Metachunk* chunks = chunks_in_use(i);
+ if (chunks != NULL) {
+ chunks->reset_container();
+ }
+ }
+}
+
size_t SpaceManager::adjust_initial_chunk_size(size_t requested, bool is_class_space) {
size_t chunk_sizes[] = {
specialized_chunk_size(is_class_space),
@@ -3002,6 +3012,10 @@ Metaspace::~Metaspace() {
}
}
+void Metaspace::reset_metachunks() {
+ vsm()->reset_metachunks();
+}
+
VirtualSpaceList* Metaspace::_space_list = NULL;
VirtualSpaceList* Metaspace::_class_space_list = NULL;
diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp
index 2b06cb62..122dd4bf 100644
--- a/hotspot/src/share/vm/memory/metaspace.hpp
+++ b/hotspot/src/share/vm/memory/metaspace.hpp
@@ -243,6 +243,8 @@ class Metaspace : public CHeapObj<mtClass> {
MetaWord* expand_and_allocate(size_t size,
MetadataType mdtype);
+ void reset_metachunks();
+
static bool contains(const void* ptr);
void dump(outputStream* const out) const;
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
index 00fb9fe9..b31d0a3f 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
@@ -205,6 +205,21 @@ static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) {
}
}
+static void patch_deallocate_meta_vtables(void** vtbl_list, void* new_vtable_start, GrowableArray<Metadata*>* deallocate_list) {
+ if (deallocate_list == NULL) {
+ return;
+ }
+ for (int i = deallocate_list->length() - 1; i >= 0; i--) {
+ Metadata* m = deallocate_list->at(i);
+ if (!m->on_stack()) {
+ if (m->is_constantPool()) {
+ ((ConstantPool*)m)->remove_unshareable_info();
+ *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m);
+ }
+ }
+ }
+}
+
// Closure for serializing initialization data out to a data area to be
// written to the shared file.
@@ -591,6 +606,7 @@ void VM_PopulateDumpSharedSpace::doit() {
// Update the vtable pointers in all of the Klass objects in the
// heap. They should point to newly generated vtable.
patch_klass_vtables(vtbl_list, vtable);
+ patch_deallocate_meta_vtables(vtbl_list, vtable, _loader_data->_deallocate_list);
// dunno what this is for.
char* saved_vtbl = (char*)os::malloc(vtbl_list_size * sizeof(void*), mtClass);
@@ -602,6 +618,9 @@ void VM_PopulateDumpSharedSpace::doit() {
FileMapInfo* mapinfo = new FileMapInfo();
mapinfo->populate_header(MetaspaceShared::max_alignment());
+ if (Arguments::get_is_default_jsa()) {
+ mapinfo->set_is_default_jsa(true);
+ }
// Pass 1 - update file offsets in header.
mapinfo->write_header();
mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true);
@@ -997,6 +1016,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
mapinfo->verify_region_checksum(d_rw) &&
(_ro_base = mapinfo->map_region(d_ro)) != NULL &&
mapinfo->verify_region_checksum(d_ro) &&
+ (_ro_base = mapinfo->map_region(d_md)) != NULL &&
+ mapinfo->verify_region_checksum(d_md) &&
(image_alignment == (size_t)max_alignment())) {
mapinfo->set_is_mapped(true);
return true;
@@ -1153,6 +1174,7 @@ void MetaspaceShared::initialize_shared_spaces() {
ReadClosure rc(&buffer);
SymbolTable::serialize_shared_table_header(&rc);
SystemDictionaryShared::serialize_dictionary_headers(&rc);
+ ClassLoader::deserialize_package_hash_table(dynamic_mapinfo->region_base(d_md));
dynamic_mapinfo->close();
}
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp
index a9dadfbb..3eb8b12c 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp
@@ -90,8 +90,9 @@ class MetaspaceShared : AllStatic {
// core dynamic archive spaces
d_rw = 0, // read-write shared space in the heap
d_ro = 1, // read-only shared space in the heap
- d_bm = 2, // relocation bitmaps (freed after file mapping is finished)
- d_n_regions = 2 // d_rw and d_ro
+ d_md = 2, // miscellaneous data
+ d_bm = 3, // relocation bitmaps (freed after file mapping is finished)
+ d_n_regions = 3 // d_rw, d_ro, d_md
};
// Accessor functions to save shared space created for metadata, which has
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index 0d1b1a8d..9276b895 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -2633,7 +2633,7 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
// returns true IFF is_in_error_state() has been changed as a result of this call.
bool InstanceKlass::check_sharing_error_state() {
- assert(DumpSharedSpaces, "should only be called during dumping");
+ assert(DynamicDumpSharedSpaces || DumpSharedSpaces, "should only be called during dumping");
bool old_state = is_in_error_state();
if (!is_in_error_state()) {
@@ -3573,6 +3573,9 @@ void InstanceKlass::verify_on(outputStream* st) {
// Avoid redundant verifies, this really should be in product.
if (_verify_count == Universe::verify_count()) return;
_verify_count = Universe::verify_count();
+ if (is_in_error_state()) {
+ return;
+ }
#endif
// Verify Klass
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 1f603021..5a79ab7e 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -100,6 +100,7 @@ do { \
} \
} while(0)
+bool Arguments::_is_default_jsa = false;
char** Arguments::_jvm_flags_array = NULL;
int Arguments::_num_jvm_flags = 0;
char** Arguments::_jvm_args_array = NULL;
@@ -4041,23 +4042,32 @@ static void force_serial_gc() {
}
#endif // INCLUDE_ALL_GCS
+char* Arguments::get_default_shared_archive_path() {
+ char *default_archive_path;
+ char jvm_path[JVM_MAXPATHLEN];
+ os::jvm_path(jvm_path, sizeof(jvm_path));
+ char *end = strrchr(jvm_path, *os::file_separator());
+ if (end != NULL) {
+ *end = '\0';
+ }
+ size_t jvm_path_len = strlen(jvm_path);
+ size_t file_sep_len = strlen(os::file_separator());
+ const size_t len = jvm_path_len + file_sep_len + 20;
+ default_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+ if (default_archive_path != NULL) {
+ jio_snprintf(default_archive_path, len, "%s%sclasses.jsa",
+ jvm_path, os::file_separator());
+ }
+ Arguments::set_is_default_jsa(true);
+ return default_archive_path;
+}
+
// Sharing support
// Construct the path to the archive
static char* get_shared_archive_path() {
char *shared_archive_path;
if (SharedArchiveFile == NULL) {
- char jvm_path[JVM_MAXPATHLEN];
- os::jvm_path(jvm_path, sizeof(jvm_path));
- char *end = strrchr(jvm_path, *os::file_separator());
- if (end != NULL) *end = '\0';
- size_t jvm_path_len = strlen(jvm_path);
- size_t file_sep_len = strlen(os::file_separator());
- const size_t len = jvm_path_len + file_sep_len + 20;
- shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
- if (shared_archive_path != NULL) {
- jio_snprintf(shared_archive_path, len, "%s%sclasses.jsa",
- jvm_path, os::file_separator());
- }
+ shared_archive_path = Arguments::get_default_shared_archive_path();
} else {
shared_archive_path = os::strdup(SharedArchiveFile, mtInternal);
}
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
index 19f5cb60..65907eb4 100644
--- a/hotspot/src/share/vm/runtime/arguments.hpp
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
@@ -240,6 +240,8 @@ class Arguments : AllStatic {
private:
+ // Indicates whether the JSA file is the default jsa file.
+ static bool _is_default_jsa;
// an array containing all flags specified in the .hotspotrc file
static char** _jvm_flags_array;
static int _num_jvm_flags;
@@ -487,6 +489,9 @@ class Arguments : AllStatic {
// Return the maximum size a heap with compressed oops can take
static size_t max_heap_for_compressed_oops();
+ static void set_is_default_jsa(bool is_default) { _is_default_jsa = is_default; }
+ static bool get_is_default_jsa() { return _is_default_jsa; }
+
// return a char* array containing all options
static char** jvm_flags_array() { return _jvm_flags_array; }
static char** jvm_args_array() { return _jvm_args_array; }
@@ -622,6 +627,7 @@ class Arguments : AllStatic {
static char* get_ext_dirs() { return _java_ext_dirs->value(); }
static char* get_appclasspath() { return _java_class_path->value(); }
static void fix_appclasspath();
+ static char* get_default_shared_archive_path();
// Operation modi
static Mode mode() { return _mode; }
diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp
index 66df8f1f..df290d99 100644
--- a/hotspot/src/share/vm/utilities/hashtable.cpp
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp
@@ -58,6 +58,7 @@ template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsig
len = 1 << log2_int(len); // round down to power of 2
assert(len >= _entry_size, "");
_first_free_entry = NEW_C_HEAP_ARRAY2(char, len, F, CURRENT_PC);
+ memset(_first_free_entry, 0, len);
_end_block = _first_free_entry + len;
}
entry = (BasicHashtableEntry<F>*)_first_free_entry;
diff --git a/hotspot/test/runtime/appcds/TestCommon.java b/hotspot/test/runtime/appcds/TestCommon.java
index 22eef4ed..6a61dc31 100644
--- a/hotspot/test/runtime/appcds/TestCommon.java
+++ b/hotspot/test/runtime/appcds/TestCommon.java
@@ -54,6 +54,7 @@ public class TestCommon extends CDSTestUtils {
System.getProperty("test.timeout.factor", "1.0");
private static String currentArchiveName;
+ private static String topArchiveName;
// Call this method to start new archive with new unique name
public static void startNewArchiveName() {
@@ -62,6 +63,13 @@ public class TestCommon extends CDSTestUtils {
timeStampFormat.format(new Date()) + ".jsa";
}
+ public static String getTopArchiveName() {
+ topArchiveName = System.getProperty("user.dir") +
+ File.separator + "d-appcds-" + timeStampFormat.format(new Date()) + ".jsa";
+ currentArchiveName = topArchiveName;
+ return topArchiveName;
+ }
+
// Call this method to get current archive name
public static String getCurrentArchiveName() {
return currentArchiveName;
@@ -90,6 +98,16 @@ public class TestCommon extends CDSTestUtils {
}
}
+ public static void deletePriorTopArchives() {
+ File dir = new File(System.getProperty("user.dir"));
+ String files[] = dir.list();
+ for (String name : files) {
+ if (name.startsWith("d-appcds-") && name.endsWith(".jsa")) {
+ if (!(new File(dir, name)).delete())
+ System.out.println("deletePriorArchives(): delete failed for file " + name);
+ }
+ }
+ }
// Create AppCDS archive using most common args - convenience method
// Legacy name preserved for compatibility
@@ -132,7 +150,6 @@ public class TestCommon extends CDSTestUtils {
cmd.add("-Xshare:dump");
cmd.add("-XX:+UseAppCDS");
-// cmd.add("-Xlog:cds,cds+hashtables"); comment out because it will be run by jdk1.8
cmd.add("-XX:ExtraSharedClassListFile=" + classList.getPath());
if (opts.archiveName == null)
@@ -147,6 +164,36 @@ public class TestCommon extends CDSTestUtils {
return executeAndLog(pb, "dump");
}
+ public static OutputAnalyzer createBaseArchive(String appJar, String appClasses[], String... suffix)
+ throws Exception {
+ return createArchive(appJar, appClasses, suffix);
+ }
+
+ public static OutputAnalyzer createTopArchive(String appJar, String...suffix)
+ throws Exception {
+ AppCDSOptions opts = new AppCDSOptions();
+ opts.setAppJar(appJar);
+ opts.addSuffix(suffix);
+
+ ArrayList<String> cmd = new ArrayList<String>();
+ cmd.add("-cp");
+ cmd.add(opts.appJar);
+
+ String baseArchiveName = getCurrentArchiveName();
+ deletePriorTopArchives();
+ String topArchiveNmae = getTopArchiveName();
+ cmd.add("-XX:+UnlockExperimentalVMOptions");
+ cmd.add("-Xshare:on");
+ cmd.add("-XX:SharedArchiveFile=" + baseArchiveName);
+ cmd.add("-XX:ArchiveClassesAtExit=" + topArchiveNmae);
+ cmd.add("-XX:+InfoDynamicCDS");
+
+ for (String s : opts.suffix) cmd.add(s);
+
+ String[] cmdLine = cmd.toArray(new String[cmd.size()]);
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, makeCommandLineForAppCDS(cmdLine));
+ return executeAndLog(pb, "dump");
+ }
// Execute JVM using AppCDS archive with specified AppCDSOptions
public static OutputAnalyzer runWithArchive(AppCDSOptions opts)
@@ -156,6 +203,9 @@ public class TestCommon extends CDSTestUtils {
for (String p : opts.prefix) cmd.add(p);
+ if (topArchiveName != null) {
+ cmd.add("-XX:+InfoDynamicCDS");
+ }
cmd.add("-Xshare:" + opts.xShareMode);
cmd.add("-XX:+UseAppCDS");
cmd.add("-showversion");
@@ -174,7 +224,6 @@ public class TestCommon extends CDSTestUtils {
return executeAndLog(pb, "exec");
}
-
public static OutputAnalyzer execCommon(String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions());
opts.addSuffix(suffix);
@@ -261,6 +310,27 @@ public class TestCommon extends CDSTestUtils {
}
+ public static OutputAnalyzer testDynamicCDS(String appJar, String appClasses[], String... args)
+ throws Exception {
+ // Create base archive
+ OutputAnalyzer output = createBaseArchive(appJar, appClasses, args);
+ output.shouldContain("Loading classes to share");
+ output.shouldHaveExitValue(0);
+
+ // Create top archive
+ output = createTopArchive(appJar, args);
+ output.shouldContain("Written dynamic archive");
+ output.shouldHaveExitValue(0);
+
+ // Exec with top archive
+ output = exec(appJar, args);
+
+ // Check exec result
+ checkMatches(output, "SharedArchivePath", "SharedDynamicArchivePath");
+ output.shouldHaveExitValue(0);
+ return output;
+ }
+
public static OutputAnalyzer checkExecReturn(OutputAnalyzer output, int ret,
boolean checkContain, String... matches) throws Exception {
try {
diff --git a/hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java b/hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java
new file mode 100644
index 00000000..79f30759
--- /dev/null
+++ b/hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. 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 The DynamicDumpShareSpaces flag is internal, setting it at the command line should have no effect.
+ * @library /testlibrary /runtime/appcds /runtime/appcds/test-classes
+ * @compile ../test-classes/Hello.java
+ * @run driver DynamicFlag
+ */
+
+public class DynamicFlag {
+ public static void main(String[] args) throws Exception {
+ TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+ TestCommon.list("Hello"), "-XX:+DynamicDumpSharedSpaces", "Hello");
+ }
+}
diff --git a/hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java b/hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java
new file mode 100644
index 00000000..48e97cb2
--- /dev/null
+++ b/hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. 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 Hello World test for dynamic cds
+ * @library /testlibrary /runtime/appcds /runtime/appcds/test-classes
+ * @compile ../test-classes/Hello.java
+ * @run main DynamicHelloTest
+ */
+
+public class DynamicHelloTest {
+ public static void main(String[] args) throws Exception {
+ TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+ null, "Hello");
+
+ TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+ TestCommon.list("Hello"), "Hello");
+ }
+}
diff --git a/hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java b/hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java
new file mode 100644
index 00000000..eacc1aff
--- /dev/null
+++ b/hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. 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 Hello World test for dynamic cds
+ * @library /testlibrary /runtime/appcds /runtime/appcds/test-classes
+ * @compile ../test-classes/Hello.java
+ * @run main VerifyWithDynamicArchive
+ */
+
+public class VerifyWithDynamicArchive {
+ public static void main(String[] args) throws Exception {
+ TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+ null, "-XX:+VerifySharedSpaces", "Hello");
+
+ TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+ TestCommon.list("Hello"), "-XX:+VerifySharedSpaces", "Hello");
+ }
+}
diff --git a/jdk/make/BuildJdk.gmk b/jdk/make/BuildJdk.gmk
index 467792fa..bb8ea8a9 100644
--- a/jdk/make/BuildJdk.gmk
+++ b/jdk/make/BuildJdk.gmk
@@ -103,6 +103,13 @@ images:
ifeq ($(OPENJDK_TARGET_OS), macosx)
+$(MAKE) -f Bundles.gmk
endif
+ ifeq ($(BUILD_CDS_ARCHIVE), true)
+ echo Creating CDS archive for jdk image
+ $(JDK_IMAGE_DIR)/bin/java -Xshare:dump -Xmx128M -Xms128M -XX:ParallelGCThreads=1 -Xint $(LOG_INFO)
+ echo Creating CDS archive for jre image
+ $(JRE_IMAGE_DIR)/bin/java -Xshare:dump -Xmx128M -Xms128M -XX:ParallelGCThreads=1 -Xint $(LOG_INFO)
+ endif
+
overlay-images:
+$(MAKE) -f CompileLaunchers.gmk OVERLAY_IMAGES=true
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。