8296754: AutoCreateSharedArchive in JDK 20 is not compatible with JDK 19
Reviewed-by: ccheung, iklam, erikj
This commit is contained in:
parent
405b1886b3
commit
a249a52501
@ -770,10 +770,13 @@ define SetupRunJtregTestBody
|
||||
# Make sure the tmp dir is normalized as some tests will react badly otherwise
|
||||
$1_TEST_TMP_DIR := $$(abspath $$($1_TEST_SUPPORT_DIR)/tmp)
|
||||
|
||||
# test.boot.jdk is used by some test cases that want to execute a previous
|
||||
# version of the JDK.
|
||||
$1_JTREG_BASIC_OPTIONS += -$$($1_JTREG_TEST_MODE) \
|
||||
-verbose:$$(JTREG_VERBOSE) -retain:$$(JTREG_RETAIN) \
|
||||
-concurrency:$$($1_JTREG_JOBS) -timeoutFactor:$$(JTREG_TIMEOUT_FACTOR) \
|
||||
-vmoption:-XX:MaxRAMPercentage=$$($1_JTREG_MAX_RAM_PERCENTAGE) \
|
||||
-vmoption:-Dtest.boot.jdk="$$(BOOT_JDK)" \
|
||||
-vmoption:-Djava.io.tmpdir="$$($1_TEST_TMP_DIR)"
|
||||
|
||||
$1_JTREG_BASIC_OPTIONS += -automatic -ignore:quiet
|
||||
|
@ -30,18 +30,18 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
CDSConst CDSConstants::offsets[] = {
|
||||
{ "GenericCDSFileMapHeader::_magic", offset_of(GenericCDSFileMapHeader, _magic) },
|
||||
{ "GenericCDSFileMapHeader::_crc", offset_of(GenericCDSFileMapHeader, _crc) },
|
||||
{ "GenericCDSFileMapHeader::_version", offset_of(GenericCDSFileMapHeader, _version) },
|
||||
{ "GenericCDSFileMapHeader::_header_size", offset_of(GenericCDSFileMapHeader, _header_size) },
|
||||
{ "GenericCDSFileMapHeader::_common_app_classpath_prefix_size", offset_of(GenericCDSFileMapHeader, _common_app_classpath_prefix_size) },
|
||||
{ "GenericCDSFileMapHeader::_base_archive_name_offset", offset_of(GenericCDSFileMapHeader, _base_archive_name_offset) },
|
||||
{ "GenericCDSFileMapHeader::_base_archive_name_size", offset_of(GenericCDSFileMapHeader, _base_archive_name_size) },
|
||||
{ "CDSFileMapHeaderBase::_regions[0]", offset_of(CDSFileMapHeaderBase, _regions) },
|
||||
{ "FileMapHeader::_jvm_ident", offset_of(FileMapHeader, _jvm_ident) },
|
||||
{ "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc) },
|
||||
{ "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used) },
|
||||
{ "DynamicArchiveHeader::_base_region_crc", offset_of(DynamicArchiveHeader, _base_region_crc) }
|
||||
{ "GenericCDSFileMapHeader::_magic", offset_of(GenericCDSFileMapHeader, _magic) },
|
||||
{ "GenericCDSFileMapHeader::_crc", offset_of(GenericCDSFileMapHeader, _crc) },
|
||||
{ "GenericCDSFileMapHeader::_version", offset_of(GenericCDSFileMapHeader, _version) },
|
||||
{ "GenericCDSFileMapHeader::_header_size", offset_of(GenericCDSFileMapHeader, _header_size) },
|
||||
{ "GenericCDSFileMapHeader::_base_archive_name_offset", offset_of(GenericCDSFileMapHeader, _base_archive_name_offset) },
|
||||
{ "GenericCDSFileMapHeader::_base_archive_name_size", offset_of(GenericCDSFileMapHeader, _base_archive_name_size) },
|
||||
{ "CDSFileMapHeaderBase::_regions[0]", offset_of(CDSFileMapHeaderBase, _regions) },
|
||||
{ "FileMapHeader::_jvm_ident", offset_of(FileMapHeader, _jvm_ident) },
|
||||
{ "FileMapHeader::_common_app_classpath_prefix_size", offset_of(FileMapHeader, _common_app_classpath_prefix_size) },
|
||||
{ "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc) },
|
||||
{ "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used) },
|
||||
{ "DynamicArchiveHeader::_base_region_crc", offset_of(DynamicArchiveHeader, _base_region_crc) }
|
||||
};
|
||||
|
||||
CDSConst CDSConstants::constants[] = {
|
||||
|
@ -1267,10 +1267,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_common_app_classpath_prefix_len()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All fields in the GenericCDSFileMapHeader has been validated.
|
||||
_is_valid = true;
|
||||
return true;
|
||||
@ -1351,15 +1347,6 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_common_app_classpath_prefix_len() {
|
||||
int common_path_size = _header->_common_app_classpath_prefix_size;
|
||||
if (common_path_size < 0) {
|
||||
FileMapInfo::fail_continue("common app classpath prefix len < 0");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Return value:
|
||||
@ -1434,6 +1421,12 @@ bool FileMapInfo::init_from_file(int fd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int common_path_size = header()->common_app_classpath_prefix_size();
|
||||
if (common_path_size < 0) {
|
||||
FileMapInfo::fail_continue("common app classpath prefix len < 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int base_offset = header()->base_archive_name_offset();
|
||||
unsigned int name_size = header()->base_archive_name_size();
|
||||
unsigned int header_size = header()->header_size();
|
||||
|
@ -189,21 +189,23 @@ private:
|
||||
// The following fields record the states of the VM during dump time.
|
||||
// They are compared with the runtime states to see if the archive
|
||||
// can be used.
|
||||
size_t _core_region_alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
bool _compressed_oops; // save the flag UseCompressedOops
|
||||
bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers
|
||||
size_t _cloned_vtables_offset; // The address of the first cloned vtable
|
||||
size_t _serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize()
|
||||
address _heap_begin; // heap begin at dump time.
|
||||
address _heap_end; // heap end at dump time.
|
||||
bool _has_non_jar_in_classpath; // non-jar file entry exists in classpath
|
||||
size_t _core_region_alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
bool _compressed_oops; // save the flag UseCompressedOops
|
||||
bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers
|
||||
size_t _cloned_vtables_offset; // The address of the first cloned vtable
|
||||
size_t _serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize()
|
||||
address _heap_begin; // heap begin at dump time.
|
||||
address _heap_end; // heap end at dump time.
|
||||
bool _has_non_jar_in_classpath; // non-jar file entry exists in classpath
|
||||
unsigned int _common_app_classpath_prefix_size; // size of the common prefix of app class paths
|
||||
// 0 if no common prefix exists
|
||||
|
||||
// The following fields are all sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
@ -240,21 +242,21 @@ private:
|
||||
void set_as_offset(char* p, size_t *offset);
|
||||
public:
|
||||
// Accessors -- fields declared in GenericCDSFileMapHeader
|
||||
unsigned int magic() const { return _generic_header._magic; }
|
||||
int crc() const { return _generic_header._crc; }
|
||||
int version() const { return _generic_header._version; }
|
||||
unsigned int header_size() const { return _generic_header._header_size; }
|
||||
unsigned int base_archive_name_offset() const { return _generic_header._base_archive_name_offset; }
|
||||
unsigned int base_archive_name_size() const { return _generic_header._base_archive_name_size; }
|
||||
unsigned int common_app_classpath_prefix_size() const { return _generic_header._common_app_classpath_prefix_size; }
|
||||
unsigned int magic() const { return _generic_header._magic; }
|
||||
int crc() const { return _generic_header._crc; }
|
||||
int version() const { return _generic_header._version; }
|
||||
unsigned int header_size() const { return _generic_header._header_size; }
|
||||
unsigned int base_archive_name_offset() const { return _generic_header._base_archive_name_offset; }
|
||||
unsigned int base_archive_name_size() const { return _generic_header._base_archive_name_size; }
|
||||
unsigned int common_app_classpath_prefix_size() const { return _common_app_classpath_prefix_size; }
|
||||
|
||||
void set_magic(unsigned int m) { _generic_header._magic = m; }
|
||||
void set_crc(int crc_value) { _generic_header._crc = crc_value; }
|
||||
void set_version(int v) { _generic_header._version = v; }
|
||||
void set_header_size(unsigned int s) { _generic_header._header_size = s; }
|
||||
void set_base_archive_name_offset(unsigned int s) { _generic_header._base_archive_name_offset = s; }
|
||||
void set_base_archive_name_size(unsigned int s) { _generic_header._base_archive_name_size = s; }
|
||||
void set_common_app_classpath_prefix_size(unsigned int s) { _generic_header._common_app_classpath_prefix_size = s; }
|
||||
void set_magic(unsigned int m) { _generic_header._magic = m; }
|
||||
void set_crc(int crc_value) { _generic_header._crc = crc_value; }
|
||||
void set_version(int v) { _generic_header._version = v; }
|
||||
void set_header_size(unsigned int s) { _generic_header._header_size = s; }
|
||||
void set_base_archive_name_offset(unsigned int s) { _generic_header._base_archive_name_offset = s; }
|
||||
void set_base_archive_name_size(unsigned int s) { _generic_header._base_archive_name_size = s; }
|
||||
void set_common_app_classpath_prefix_size(unsigned int s) { _common_app_classpath_prefix_size = s; }
|
||||
|
||||
size_t core_region_alignment() const { return _core_region_alignment; }
|
||||
int obj_alignment() const { return _obj_alignment; }
|
||||
|
@ -39,7 +39,7 @@
|
||||
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
||||
#define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
|
||||
#define CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION 13
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 16
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 17
|
||||
|
||||
typedef struct CDSFileMapRegion {
|
||||
int _crc; // CRC checksum of this region.
|
||||
@ -73,8 +73,6 @@ typedef struct GenericCDSFileMapHeader {
|
||||
int _crc; // header crc checksum, start from _base_archive_name_offset
|
||||
int _version; // CURRENT_CDS_ARCHIVE_VERSION of the jdk that dumped the this archive
|
||||
unsigned int _header_size; // total size of the header, in bytes
|
||||
unsigned int _common_app_classpath_prefix_size; // size of the common prefix of app class paths
|
||||
// 0 if no common prefix exists
|
||||
unsigned int _base_archive_name_offset; // offset where the base archive name is stored
|
||||
// static archive: 0
|
||||
// dynamic archive:
|
||||
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Check that -XX:+AutoCreateSharedArchive automatically recreates an archive when you change the JDK version.
|
||||
* @requires os.family == "linux" & vm.bits == "64" & (os.arch=="amd64" | os.arch=="x86_64")
|
||||
* @library /test/lib
|
||||
* @compile -source 1.8 -target 1.8 ../test-classes/HelloJDK8.java
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar Hello.jar HelloJDK8
|
||||
* @run driver TestAutoCreateSharedArchiveUpgrade
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.test.lib.helpers.ClassFileInstaller;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class TestAutoCreateSharedArchiveUpgrade {
|
||||
// The JDK being tested
|
||||
private static final String TEST_JDK = System.getProperty("test.jdk", null);
|
||||
|
||||
// If you're running this test manually, specify the location of a previous version of
|
||||
// the JDK using "jtreg -vmoption:-Dtest.previous.jdk=${JDK19_HOME} ..."
|
||||
private static final String PREV_JDK = System.getProperty("test.previous.jdk", null);
|
||||
|
||||
// If you're unning this test using something like
|
||||
// "make test TEST=test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveUpgrade.java",
|
||||
// the test.boot.jdk property is passed by make/RunTests.gmk
|
||||
private static final String BOOT_JDK = System.getProperty("test.boot.jdk", null);
|
||||
|
||||
private static final String USER_DIR = System.getProperty("user.dir", ".");
|
||||
private static final String FS = System.getProperty("file.separator", "/");
|
||||
|
||||
private static final String JAR = ClassFileInstaller.getJarPath("Hello.jar");
|
||||
private static final String JSA = USER_DIR + FS + "Hello.jsa";
|
||||
|
||||
private static String oldJVM;
|
||||
private static String newJVM;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
setupJVMs();
|
||||
doTest();
|
||||
}
|
||||
|
||||
static void setupJVMs() throws Throwable {
|
||||
if (TEST_JDK == null) {
|
||||
throw new RuntimeException("-Dtest.jdk should point to the JDK being tested");
|
||||
}
|
||||
|
||||
newJVM = TEST_JDK + FS + "bin" + FS + "java";
|
||||
|
||||
if (PREV_JDK != null) {
|
||||
oldJVM = PREV_JDK + FS + "bin" + FS + "java";
|
||||
} else if (BOOT_JDK != null) {
|
||||
oldJVM = BOOT_JDK + FS + "bin" + FS + "java";
|
||||
} else {
|
||||
throw new RuntimeException("Use -Dtest.previous.jdk or -Dtest.boot.jdk to specify a " +
|
||||
"previous version of the JDK that supports " +
|
||||
"-XX:+AutoCreateSharedArchive");
|
||||
}
|
||||
|
||||
System.out.println("Using newJVM = " + newJVM);
|
||||
System.out.println("Using oldJVM = " + oldJVM);
|
||||
}
|
||||
|
||||
static void doTest() throws Throwable {
|
||||
File jsaF = new File(JSA);
|
||||
jsaF.delete();
|
||||
OutputAnalyzer output;
|
||||
|
||||
// NEW JDK -- create and then use the JSA
|
||||
output = run(newJVM);
|
||||
assertJSANotFound(output);
|
||||
assertCreatedJSA(output);
|
||||
|
||||
output = run(newJVM);
|
||||
assertUsedJSA(output);
|
||||
|
||||
// OLD JDK -- should reject the JSA created by NEW JDK, and create its own
|
||||
output = run(oldJVM);
|
||||
assertJSAVersionMismatch(output);
|
||||
assertCreatedJSA(output);
|
||||
|
||||
output = run(oldJVM);
|
||||
assertUsedJSA(output);
|
||||
|
||||
// NEW JDK -- should reject the JSA created by OLD JDK, and create its own
|
||||
output = run(newJVM);
|
||||
assertJSAVersionMismatch(output);
|
||||
assertCreatedJSA(output);
|
||||
|
||||
output = run(newJVM);
|
||||
assertUsedJSA(output);
|
||||
}
|
||||
|
||||
static OutputAnalyzer run(String jvm) throws Throwable {
|
||||
OutputAnalyzer output =
|
||||
ProcessTools.executeCommand(jvm, "-XX:+AutoCreateSharedArchive",
|
||||
"-XX:SharedArchiveFile=" + JSA,
|
||||
"-Xlog:cds",
|
||||
"-cp", JAR, "HelloJDK8");
|
||||
output.shouldHaveExitValue(0);
|
||||
return output;
|
||||
}
|
||||
|
||||
static void assertJSANotFound(OutputAnalyzer output) {
|
||||
output.shouldContain("Specified shared archive not found");
|
||||
}
|
||||
|
||||
static void assertCreatedJSA(OutputAnalyzer output) {
|
||||
output.shouldContain("Dumping shared data to file");
|
||||
}
|
||||
|
||||
static void assertJSAVersionMismatch(OutputAnalyzer output) {
|
||||
output.shouldContain("does not match the required version");
|
||||
}
|
||||
|
||||
static void assertUsedJSA(OutputAnalyzer output) {
|
||||
output.shouldContain("Mapped dynamic region #0");
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Used by tests like dynamicArchive/TestAutoCreateSharedArchiveUpgrade.java, which
|
||||
// runs this class in an earlier JDK
|
||||
//
|
||||
// It should be compiled like this in the jtreg spec:
|
||||
// @compile -source 1.8 -target 1.8 test-classes/HelloJDK8.java
|
||||
|
||||
public class HelloJDK8 {
|
||||
public static void main(String args[]) {
|
||||
System.out.println("This class is compiled by JDK 8");
|
||||
}
|
||||
}
|
@ -94,7 +94,7 @@ public class CDSArchiveUtils {
|
||||
offsetCrc = wb.getCDSOffsetForName("GenericCDSFileMapHeader::_crc");
|
||||
offsetVersion = wb.getCDSOffsetForName("GenericCDSFileMapHeader::_version");
|
||||
offsetHeaderSize = wb.getCDSOffsetForName("GenericCDSFileMapHeader::_header_size");
|
||||
offsetCommonAppClasspathPrefixSize = wb.getCDSOffsetForName("GenericCDSFileMapHeader::_common_app_classpath_prefix_size");
|
||||
offsetCommonAppClasspathPrefixSize = wb.getCDSOffsetForName("FileMapHeader::_common_app_classpath_prefix_size");
|
||||
offsetBaseArchiveNameOffset = wb.getCDSOffsetForName("GenericCDSFileMapHeader::_base_archive_name_offset");
|
||||
offsetBaseArchiveNameSize = wb.getCDSOffsetForName("GenericCDSFileMapHeader::_base_archive_name_size");
|
||||
offsetJvmIdent = wb.getCDSOffsetForName("FileMapHeader::_jvm_ident");
|
||||
|
Loading…
Reference in New Issue
Block a user