mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8369856: AOT map does not include unregistered classes
Co-authored-by: Ashutosh Mehra <asmehra@openjdk.org> Reviewed-by: kvn, matsaave
This commit is contained in:
parent
4d20f7696c
commit
bd7315648f
@ -1420,6 +1420,10 @@ void SystemDictionaryShared::get_all_archived_classes(bool is_static_archive, Gr
|
||||
get_archive(is_static_archive)->_builtin_dictionary.iterate([&] (const RunTimeClassInfo* record) {
|
||||
classes->append(record->klass());
|
||||
});
|
||||
|
||||
get_archive(is_static_archive)->_unregistered_dictionary.iterate([&] (const RunTimeClassInfo* record) {
|
||||
classes->append(record->klass());
|
||||
});
|
||||
}
|
||||
|
||||
class SharedDictionaryPrinter : StackObj {
|
||||
|
||||
@ -26,6 +26,7 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -33,7 +34,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
This is a simple parser for parsing the output of
|
||||
|
||||
java -Xshare:dump -Xlog:aot+map=debug,aot+map+oops=trace:file=cds.map:none:filesize=0
|
||||
java -Xshare:dump -Xlog:aot+map=debug,aot+map+oops=trace:file=aot.map:none:filesize=0
|
||||
|
||||
The map file contains patterns like this for the heap objects:
|
||||
|
||||
@ -59,8 +60,9 @@ more analysis on the HeapObjects.
|
||||
|
||||
*/
|
||||
|
||||
public class CDSMapReader {
|
||||
public class AOTMapReader {
|
||||
public static class MapFile {
|
||||
HashSet<String> classes = new HashSet<>();
|
||||
ArrayList<HeapObject> heapObjects = new ArrayList<>();
|
||||
HashMap<Long, HeapObject> oopToObject = new HashMap<>();
|
||||
HashMap<Long, HeapObject> narrowOopToObject = new HashMap<>();
|
||||
@ -80,6 +82,20 @@ public class CDSMapReader {
|
||||
public int heapObjectCount() {
|
||||
return heapObjects.size();
|
||||
}
|
||||
|
||||
void addClass(String className) {
|
||||
classes.add(className);
|
||||
}
|
||||
|
||||
public boolean hasClass(String className) {
|
||||
return classes.contains(className);
|
||||
}
|
||||
|
||||
public void shouldHaveClass(String className) {
|
||||
if (!hasClass(className)) {
|
||||
throw new RuntimeException("AOT map file is missing class " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class HeapAddress {
|
||||
@ -140,13 +156,17 @@ public class CDSMapReader {
|
||||
this.name = name;
|
||||
this.offset = Integer.parseInt(offset);
|
||||
this.referentAddress = new HeapAddress(oopStr, narrowOopStr);
|
||||
this.lineCount = CDSMapReader.lineCount;
|
||||
this.lineCount = AOTMapReader.lineCount;
|
||||
}
|
||||
}
|
||||
|
||||
// 0x00000007ffc00000: 4a5b8701 00000063 00010290 00000000 00010100 fff80003
|
||||
static Pattern rawDataPattern = Pattern.compile("^0x([0-9a-f]+): *( [0-9a-f]+)+ *$");
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Patterns for heap objects
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
// (one address)
|
||||
// 0x00000007ffc00000: @@ Object java.lang.String
|
||||
static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object ([^ ]*)");
|
||||
@ -179,6 +199,15 @@ public class CDSMapReader {
|
||||
// - injected 'module_entry' 'J' @16 0 (0x0000000000000000)
|
||||
static Pattern moduleEntryPattern = Pattern.compile("- injected 'module_entry' 'J' @[0-9]+[ ]+([0-9]+)");
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Patterns for metaspace objects
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
// 0x00000008000d1698: @@ Class 512 [Ljdk.internal.vm.FillerElement;
|
||||
// 0x00000008000d18a0: @@ Class 520 java.lang.Cloneable
|
||||
static Pattern classPattern = Pattern.compile("^0x([0-9a-f]+): @@ Class [ ]*([0-9]+) (.*)");
|
||||
|
||||
|
||||
private static Matcher match(String line, Pattern pattern) {
|
||||
Matcher m = pattern.matcher(line);
|
||||
if (m.find()) {
|
||||
@ -253,6 +282,11 @@ public class CDSMapReader {
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseClassObject(String className, String addr, String size) throws IOException {
|
||||
mapFile.addClass(className);
|
||||
nextLine();
|
||||
}
|
||||
|
||||
static MapFile mapFile;
|
||||
static BufferedReader reader;
|
||||
static String line = null; // current line being parsed
|
||||
@ -277,6 +311,8 @@ public class CDSMapReader {
|
||||
parseHeapObject(m.group(3), m.group(1), m.group(2));
|
||||
} else if ((m = match(line, objPattern1)) != null) {
|
||||
parseHeapObject(m.group(2), m.group(1), null);
|
||||
} else if ((m = match(line, classPattern)) != null) {
|
||||
parseClassObject(m.group(3), m.group(1), m.group(2)); // name, addr, size
|
||||
} else {
|
||||
nextLine();
|
||||
}
|
||||
@ -303,8 +339,15 @@ public class CDSMapReader {
|
||||
}
|
||||
}
|
||||
|
||||
public static void validate(MapFile mapFile, String classLoadLogFile) throws IOException {
|
||||
validateOops(mapFile);
|
||||
if (classLoadLogFile != null) {
|
||||
validateClasses(mapFile, classLoadLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that each oop fields in the HeapObjects must point to a valid HeapObject.
|
||||
public static void validate(MapFile mapFile) {
|
||||
static void validateOops(MapFile mapFile) {
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
for (HeapObject heapObject : mapFile.heapObjects) {
|
||||
@ -333,10 +376,10 @@ public class CDSMapReader {
|
||||
if (mapFile.heapObjectCount() > 0) {
|
||||
// heapObjectCount() may be zero if the selected GC doesn't support heap object archiving.
|
||||
if (mapFile.stringCount <= 0) {
|
||||
throw new RuntimeException("CDS map file should contain at least one string");
|
||||
throw new RuntimeException("AOT map file should contain at least one string");
|
||||
}
|
||||
if (count1 < mapFile.stringCount) {
|
||||
throw new RuntimeException("CDS map file seems incorrect: " + mapFile.heapObjectCount() +
|
||||
throw new RuntimeException("AOT map file seems incorrect: " + mapFile.heapObjectCount() +
|
||||
" objects (" + mapFile.stringCount + " strings). Each string should" +
|
||||
" have one non-null oop field but we found only " + count1 +
|
||||
" non-null oop field references");
|
||||
@ -344,8 +387,26 @@ public class CDSMapReader {
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
// classLoadLogFile should be generated with -Xlog:class+load:file=<classLoadLogFile>:none:filesize=0
|
||||
// Check that every class loaded from "source: shared objects file" have an entry inside the mapFile.
|
||||
static void validateClasses(MapFile mapFile, String classLoadLogFile) throws IOException {
|
||||
try (BufferedReader r = new BufferedReader(new FileReader(classLoadLogFile))) {
|
||||
String line;
|
||||
String suffix = " source: shared objects file";
|
||||
int suffixLen = suffix.length();
|
||||
while ((line = r.readLine()) != null) {
|
||||
if (line.endsWith(suffix)) {
|
||||
String className = line.substring(0, line.length() - suffixLen);
|
||||
if (!mapFile.hasClass(className)) {
|
||||
throw new RuntimeException("AOT map file is missing class " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws IOException {
|
||||
MapFile mapFile = read(args[0]);
|
||||
validate(mapFile);
|
||||
validate(mapFile, null);
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@
|
||||
* @summary Test the contents of -Xlog:aot+map
|
||||
* @requires vm.cds
|
||||
* @library /test/lib
|
||||
* @run driver/timeout=240 CDSMapTest
|
||||
* @run driver/timeout=240 AOTMapTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.cds.CDSOptions;
|
||||
@ -37,7 +37,7 @@ import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CDSMapTest {
|
||||
public class AOTMapTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
doTest(false);
|
||||
|
||||
@ -79,8 +79,8 @@ public class CDSMapTest {
|
||||
.addSuffix(args);
|
||||
CDSTestUtils.createArchiveAndCheck(opts);
|
||||
|
||||
CDSMapReader.MapFile mapFile = CDSMapReader.read(mapName);
|
||||
CDSMapReader.validate(mapFile);
|
||||
AOTMapReader.MapFile mapFile = AOTMapReader.read(mapName);
|
||||
AOTMapReader.validate(mapFile, null);
|
||||
|
||||
return archiveName;
|
||||
}
|
||||
@ -98,7 +98,7 @@ public class CDSMapTest {
|
||||
OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "exec");
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
CDSMapReader.MapFile mapFile = CDSMapReader.read(mapName);
|
||||
CDSMapReader.validate(mapFile);
|
||||
AOTMapReader.MapFile mapFile = AOTMapReader.read(mapName);
|
||||
AOTMapReader.validate(mapFile, null);
|
||||
}
|
||||
}
|
||||
@ -26,9 +26,10 @@
|
||||
* @bug 8362566
|
||||
* @summary Test the contents of -Xlog:aot+map with AOT workflow
|
||||
* @requires vm.cds.supports.aot.class.linking
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds
|
||||
* @build AOTMapTest
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
|
||||
* @build AOTMapTest Hello
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTMapTestApp
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar Hello
|
||||
* @run driver/timeout=240 AOTMapTest AOT --two-step-training
|
||||
*/
|
||||
|
||||
@ -37,15 +38,18 @@
|
||||
* @bug 8362566
|
||||
* @summary Test the contents of -Xlog:aot+map with dynamic CDS archive
|
||||
* @requires vm.cds.supports.aot.class.linking
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
|
||||
* @build jdk.test.whitebox.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
||||
* @build AOTMapTest
|
||||
* @build AOTMapTest Hello
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTMapTestApp
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar Hello
|
||||
* @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. AOTMapTest DYNAMIC
|
||||
*/
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import jdk.test.lib.cds.CDSAppTester;
|
||||
import jdk.test.lib.helpers.ClassFileInstaller;
|
||||
@ -54,6 +58,7 @@ import jdk.test.lib.Platform;
|
||||
public class AOTMapTest {
|
||||
static final String appJar = ClassFileInstaller.getJarPath("app.jar");
|
||||
static final String mainClass = "AOTMapTestApp";
|
||||
static final String classLoadLogFile = "production.class.load.log";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
doTest(args);
|
||||
@ -63,13 +68,25 @@ public class AOTMapTest {
|
||||
Tester tester = new Tester();
|
||||
tester.run(args);
|
||||
|
||||
validate(tester.dumpMapFile);
|
||||
validate(tester.runMapFile);
|
||||
if (tester.isDynamicWorkflow()) {
|
||||
// For dynamic workflow, the AOT map file doesn't include classes in the base archive, so
|
||||
// AOTMapReader.validateClasses() will fail.
|
||||
validate(tester.dumpMapFile, false);
|
||||
} else {
|
||||
validate(tester.dumpMapFile, true);
|
||||
}
|
||||
validate(tester.runMapFile, true);
|
||||
}
|
||||
|
||||
static void validate(String mapFileName) {
|
||||
CDSMapReader.MapFile mapFile = CDSMapReader.read(mapFileName);
|
||||
CDSMapReader.validate(mapFile);
|
||||
static void validate(String mapFileName, boolean checkClases) throws Exception {
|
||||
AOTMapReader.MapFile mapFile = AOTMapReader.read(mapFileName);
|
||||
if (checkClases) {
|
||||
AOTMapReader.validate(mapFile, classLoadLogFile);
|
||||
} else {
|
||||
AOTMapReader.validate(mapFile, null);
|
||||
}
|
||||
mapFile.shouldHaveClass("AOTMapTestApp"); // built-in class
|
||||
mapFile.shouldHaveClass("Hello"); // unregistered class
|
||||
}
|
||||
|
||||
static class Tester extends CDSAppTester {
|
||||
@ -97,12 +114,13 @@ public class AOTMapTest {
|
||||
|
||||
// filesize=0 ensures that a large map file not broken up in multiple files.
|
||||
String logMapPrefix = "-Xlog:aot+map=debug,aot+map+oops=trace:file=";
|
||||
String logMapSuffix = ":none:filesize=0";
|
||||
String logSuffix = ":none:filesize=0";
|
||||
|
||||
if (runMode == RunMode.ASSEMBLY || runMode == RunMode.DUMP_DYNAMIC) {
|
||||
vmArgs.add(logMapPrefix + dumpMapFile + logMapSuffix);
|
||||
vmArgs.add(logMapPrefix + dumpMapFile + logSuffix);
|
||||
} else if (runMode == RunMode.PRODUCTION) {
|
||||
vmArgs.add(logMapPrefix + runMapFile + logMapSuffix);
|
||||
vmArgs.add(logMapPrefix + runMapFile + logSuffix);
|
||||
vmArgs.add("-Xlog:class+load:file=" + classLoadLogFile + logSuffix);
|
||||
}
|
||||
|
||||
return vmArgs.toArray(new String[vmArgs.size()]);
|
||||
@ -118,7 +136,16 @@ public class AOTMapTest {
|
||||
}
|
||||
|
||||
class AOTMapTestApp {
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Hello AOTMapTestApp");
|
||||
testCustomLoader();
|
||||
}
|
||||
|
||||
static void testCustomLoader() throws Exception {
|
||||
File custJar = new File("cust.jar");
|
||||
URL[] urls = new URL[] {custJar.toURI().toURL()};
|
||||
URLClassLoader loader = new URLClassLoader(urls, AOTMapTestApp.class.getClassLoader());
|
||||
Class<?> c = loader.loadClass("Hello");
|
||||
System.out.println(c);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user