Projects
Mega:23.09
openjdk-1.8.0
_service:tar_scm:8202951-Support-default-jsa.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:8202951-Support-default-jsa.patch of Package openjdk-1.8.0
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2