--- a/src/hotspot/share/memory/heapShared.cpp Mon Nov 19 09:57:41 2018 -0800
+++ b/src/hotspot/share/memory/heapShared.cpp Tue Nov 20 21:12:46 2018 +0100
@@ -64,6 +64,10 @@
// assigned at runtime.
static ArchivableStaticFieldInfo closed_archive_subgraph_entry_fields[] = {
{"java/lang/Integer$IntegerCache", "archivedCache"},
+ {"java/lang/Long$LongCache", "archivedCache"},
+ {"java/lang/Byte$ByteCache", "archivedCache"},
+ {"java/lang/Short$ShortCache", "archivedCache"},
+ {"java/lang/Character$CharacterCache", "archivedCache"},
};
// Entry fields for subgraphs archived in the open archive heap region.
static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = {
--- a/src/java.base/share/classes/java/lang/Byte.java Mon Nov 19 09:57:41 2018 -0800
+++ b/src/java.base/share/classes/java/lang/Byte.java Tue Nov 20 21:12:46 2018 +0100
@@ -26,6 +26,7 @@
package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.VM;
/**
*
@@ -77,13 +78,25 @@
}
private static class ByteCache {
- private ByteCache(){}
+ private ByteCache() {}
- static final Byte cache[] = new Byte[-(-128) + 127 + 1];
+ static final Byte[] cache;
+ static Byte[] archivedCache;
static {
- for(int i = 0; i < cache.length; i++)
- cache[i] = new Byte((byte)(i - 128));
+ final int size = -(-128) + 127 + 1;
+
+ // Load and use the archived cache if it exists
+ VM.initializeFromArchive(ByteCache.class);
+ if (archivedCache == null || archivedCache.length != size) {
+ Byte[] c = new Byte[size];
+ byte value = (byte)-128;
+ for(int i = 0; i < size; i++) {
+ c[i] = new Byte(value++);
+ }
+ archivedCache = c;
+ }
+ cache = archivedCache;
}
}
--- a/src/java.base/share/classes/java/lang/Character.java Mon Nov 19 09:57:41 2018 -0800
+++ b/src/java.base/share/classes/java/lang/Character.java Tue Nov 20 21:12:46 2018 +0100
@@ -31,6 +31,7 @@
import java.util.Locale;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.VM;
/**
* The {@code Character} class wraps a value of the primitive
@@ -7914,11 +7915,22 @@
private static class CharacterCache {
private CharacterCache(){}
- static final Character cache[] = new Character[127 + 1];
+ static final Character[] cache;
+ static Character[] archivedCache;
static {
- for (int i = 0; i < cache.length; i++)
- cache[i] = new Character((char)i);
+ int size = 127 + 1;
+
+ // Load and use the archived cache if it exists
+ VM.initializeFromArchive(CharacterCache.class);
+ if (archivedCache == null || archivedCache.length != size) {
+ Character[] c = new Character[size];
+ for (int i = 0; i < size; i++) {
+ c[i] = new Character((char) i);
+ }
+ archivedCache = c;
+ }
+ cache = archivedCache;
}
}
--- a/src/java.base/share/classes/java/lang/Integer.java Mon Nov 19 09:57:41 2018 -0800
+++ b/src/java.base/share/classes/java/lang/Integer.java Tue Nov 20 21:12:46 2018 +0100
@@ -1013,10 +1013,9 @@
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
- int i = parseInt(integerCacheHighPropValue);
- i = Math.max(i, 127);
+ h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
- h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
+ h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
@@ -1031,8 +1030,9 @@
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
- for(int k = 0; k < c.length; k++)
- c[k] = new Integer(j++);
+ for(int i = 0; i < c.length; i++) {
+ c[i] = new Integer(j++);
+ }
archivedCache = c;
}
cache = archivedCache;
--- a/src/java.base/share/classes/java/lang/Long.java Mon Nov 19 09:57:41 2018 -0800
+++ b/src/java.base/share/classes/java/lang/Long.java Tue Nov 20 21:12:46 2018 +0100
@@ -29,6 +29,7 @@
import java.math.*;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.VM;
import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.LATIN1;
@@ -1145,13 +1146,25 @@
}
private static class LongCache {
- private LongCache(){}
+ private LongCache() {}
- static final Long cache[] = new Long[-(-128) + 127 + 1];
+ static final Long[] cache;
+ static Long[] archivedCache;
static {
- for(int i = 0; i < cache.length; i++)
- cache[i] = new Long(i - 128);
+ int size = -(-128) + 127 + 1;
+
+ // Load and use the archived cache if it exists
+ VM.initializeFromArchive(LongCache.class);
+ if (archivedCache == null || archivedCache.length != size) {
+ Long[] c = new Long[size];
+ long value = -128;
+ for(int i = 0; i < size; i++) {
+ c[i] = new Long(value++);
+ }
+ archivedCache = c;
+ }
+ cache = archivedCache;
}
}
--- a/src/java.base/share/classes/java/lang/Short.java Mon Nov 19 09:57:41 2018 -0800
+++ b/src/java.base/share/classes/java/lang/Short.java Tue Nov 20 21:12:46 2018 +0100
@@ -26,6 +26,7 @@
package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.VM;
/**
* The {@code Short} class wraps a value of primitive type {@code
@@ -203,13 +204,25 @@
}
private static class ShortCache {
- private ShortCache(){}
+ private ShortCache() {}
- static final Short cache[] = new Short[-(-128) + 127 + 1];
+ static final Short[] cache;
+ static Short[] archivedCache;
static {
- for(int i = 0; i < cache.length; i++)
- cache[i] = new Short((short)(i - 128));
+ int size = -(-128) + 127 + 1;
+
+ // Load and use the archived cache if it exists
+ VM.initializeFromArchive(ShortCache.class);
+ if (archivedCache == null || archivedCache.length != size) {
+ Short[] c = new Short[size];
+ short value = -128;
+ for(int i = 0; i < size; i++) {
+ c[i] = new Short(value++);
+ }
+ archivedCache = c;
+ }
+ cache = archivedCache;
}
}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java Mon Nov 19 09:57:41 2018 -0800
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java Tue Nov 20 21:12:46 2018 +0100
@@ -152,30 +152,11 @@
klassName);
final boolean expectDisable = !early.equals("");
- final boolean checkSubgraph = subgraph;
CDSTestUtils.run(opts).assertNormalExit(out -> {
if (expectDisable) {
out.shouldContain("UseSharedSpaces: CDS is disabled because early JVMTI ClassFileLoadHook is in use.");
System.out.println("CDS disabled as expected");
}
- if (checkSubgraph) {
- // As of 2018/10/21 the classes in the archived subgraphs won't be
- // replaced because all archived subgraphs were loaded in JVMTI_PHASE_PRIMORDIAL.
- //
- // This is the first class to be loaded after JVMTI has exited JVMTI_PHASE_PRIMORDIAL.
- // Make sure no subgraphs are loaded afterwards.
- //
- // Can't use out.shouldNotMatch() because that doesn't match across multiple lines.
- String firstNonPrimordialClass = "jdk.jfr.internal.EventWriter";
- String regexp = firstNonPrimordialClass + ".*initialize_from_archived_subgraph";
- Pattern regex = Pattern.compile(regexp, Pattern.DOTALL);
- Matcher matcher = regex.matcher(out.getStdout());
- if (matcher.find()) {
- out.reportDiagnosticSummary();
- throw new RuntimeException("'" + regexp
- + "' found in stdout: '" + matcher.group() + "' \n");
- }
- }
});
}
--- a/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java Mon Nov 19 09:57:41 2018 -0800
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java Tue Nov 20 21:12:46 2018 +0100
@@ -24,7 +24,7 @@
/*
* @test
- * @summary Test IntegerCache integrity in various scenarios
+ * @summary Test primitive box caches integrity in various scenarios (IntegerCache etc)
* @requires vm.cds.archived.java.heap
* @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
@@ -32,7 +32,7 @@
* jdk.jartool/sun.tools.jar
* @build sun.hotspot.WhiteBox
* @compile CheckIntegerCacheApp.java
- * @run driver ClassFileInstaller -jar integer.jar CheckIntegerCacheApp
+ * @run driver ClassFileInstaller -jar boxCache.jar CheckIntegerCacheApp
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run driver ArchivedIntegerCacheTest
*/
@@ -47,7 +47,7 @@
public static void main(String[] args) throws Exception {
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
- String appJar = ClassFileInstaller.getJarPath("integer.jar");
+ String appJar = ClassFileInstaller.getJarPath("boxCache.jar");
Path userDir = Paths.get(System.getProperty("user.dir"));
Path moduleDir = Files.createTempDirectory(userDir, "mods");
--- a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java Mon Nov 19 09:57:41 2018 -0800
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java Tue Nov 20 21:12:46 2018 +0100
@@ -25,11 +25,13 @@
import sun.hotspot.WhiteBox;
//
-// Help test archived integer cache consistency.
+// Help test archived box cache consistency.
//
// Takes two arguments:
-// 0: the expected AutoBoxCacheMax setting
+// 0: the expected maximum value expected to be archived
// 1: if the values are expected to be retrieved from the archive or not
+// (only applies to IntegerCache; other caches should always be mapped
+// from archive)
//
public class CheckIntegerCacheApp {
static WhiteBox wb;
@@ -55,7 +57,31 @@
throw new RuntimeException(
"FAILED. All values in range [-128, 127] should be interned in cache: " + i);
}
- checkArchivedAsExpected(archivedExpected, i);
+ if (Byte.valueOf((byte)i) != Byte.valueOf((byte)i)) {
+ throw new RuntimeException(
+ "FAILED. All Byte values in range [-128, 127] should be interned in cache: " + (byte)i);
+ }
+ if (Short.valueOf((short)i) != Short.valueOf((short)i)) {
+ throw new RuntimeException(
+ "FAILED. All Short values in range [-128, 127] should be interned in cache: " + (byte)i);
+ }
+ if (Long.valueOf(i) != Long.valueOf(i)) {
+ throw new RuntimeException(
+ "FAILED. All Long values in range [-128, 127] should be interned in cache: " + i);
+ }
+ checkArchivedAsExpected(archivedExpected, Integer.valueOf(i));
+ checkArchivedAsExpected(true, Byte.valueOf((byte)i));
+ checkArchivedAsExpected(true, Short.valueOf((short)i));
+ checkArchivedAsExpected(true, Long.valueOf(i));
+
+ // Character cache only values 0 through 127
+ if (i >= 0) {
+ if (Character.valueOf((char)i) != Character.valueOf((char)i)) {
+ throw new RuntimeException(
+ "FAILED. All Character values in range [0, 127] should be interned in cache: " + i);
+ }
+ checkArchivedAsExpected(true, Character.valueOf((char)i));
+ }
}
int high = Integer.parseInt(args[0]);
@@ -70,18 +96,23 @@
"FAILED. Value not expected to be retrieved from cache: " + high);
}
checkArchivedAsExpected(false, Integer.valueOf(high + 1));
+ checkArchivedAsExpected(false, Short.valueOf((short)128));
+ checkArchivedAsExpected(false, Long.valueOf(128));
+ checkArchivedAsExpected(false, Character.valueOf((char)128));
}
- private static void checkArchivedAsExpected(boolean archivedExpected, Integer value) {
+ private static void checkArchivedAsExpected(boolean archivedExpected, Object value) {
if (archivedExpected) {
- if (!wb.isShared(Integer.valueOf(value))) {
+ if (!wb.isShared(value)) {
throw new RuntimeException(
- "FAILED. Value expected to be archived: " + value);
+ "FAILED. Value expected to be archived: " + value +
+ " of type " + value.getClass().getName());
}
} else {
- if (wb.isShared(Integer.valueOf(value))) {
+ if (wb.isShared(value)) {
throw new RuntimeException(
- "FAILED. Value not expected to be archived: " + value);
+ "FAILED. Value not expected to be archived: " + value +
+ " of type " + value.getClass().getName());
}
}
}