< prev index next > test/lib/jdk/test/lib/cds/CDSAppTester.java
Print this page
/*
* This is a base class used for testing CDS functionalities with complex applications.
* You can define the application by overridding the vmArgs(), classpath() and appCommandLine()
* methods. Application-specific validation checks can be implemented with checkExecution().
+ *
+ * Note: to debug the new workflow, run jtreg with -vmoption:-DCDSAppTester.split.new.workflow=true
+ * This will run the new workflow in two separate processes that you can rerun easily inside a debugger.
+ * Also, the log files are easier to read.
*/
abstract public class CDSAppTester {
private final String name;
private final String classListFile;
private final String classListFileLog;
private final String staticArchiveFile;
private final String staticArchiveFileLog;
private final String dynamicArchiveFile;
private final String dynamicArchiveFileLog;
+ private final String cdsFile; // new workflow: -XX:CacheDataStore=<foo>.cds
+ private final String cdsFileLog;
+ private final String cdsFilePreImage; // new workflow: -XX:CacheDataStore=<foo>.cds
+ private final String cdsFilePreImageLog;
+ private final String aotFile; // new workflow = cdsFile + ".code"
private final String tempBaseArchiveFile;
private int numProductionRuns = 0;
public CDSAppTester(String name) {
if (CDSTestUtils.DYNAMIC_DUMP) {
throw new SkippedException("Tests based on CDSAppTester should be excluded when -Dtest.dynamic.cds.archive is specified");
}
- // Old workflow
this.name = name;
classListFile = name() + ".classlist";
classListFileLog = classListFile + ".log";
staticArchiveFile = name() + ".static.jsa";
staticArchiveFileLog = staticArchiveFile + ".log";
dynamicArchiveFile = name() + ".dynamic.jsa";
dynamicArchiveFileLog = dynamicArchiveFile + ".log";
+ cdsFile = name() + ".cds";
+ cdsFileLog = cdsFile + ".log";
+ cdsFilePreImage = cdsFile + ".preimage";
+ cdsFilePreImageLog = cdsFilePreImage + ".log";
+ aotFile = cdsFile + ".code";
tempBaseArchiveFile = name() + ".temp-base.jsa";
}
private String productionRunLog() {
if (numProductionRuns == 0) {
}
private enum Workflow {
STATIC, // classic -Xshare:dump workflow
DYNAMIC, // classic -XX:ArchiveClassesAtExit
+ LEYDEN, // The new "one step training workflow" -- see JDK-8320264
}
public enum RunMode {
CLASSLIST,
DUMP_STATIC,
DUMP_DYNAMIC,
+ TRAINING, // LEYDEN only
+ TRAINING0, // LEYDEN only
+ TRAINING1, // LEYDEN only
PRODUCTION;
public boolean isStaticDump() {
return this == DUMP_STATIC;
}
public final boolean isDynamicWorkflow() {
return workflow == Workflow.DYNAMIC;
}
+ public final boolean isLeydenWorkflow() {
+ return workflow == Workflow.LEYDEN;
+ }
+
private String logToFile(String logFile, String... logTags) {
StringBuilder sb = new StringBuilder("-Xlog:");
String prefix = "";
for (String tag : logTags) {
sb.append(prefix);
listOutputFile(logFile);
}
if (checkExitValue) {
output.shouldHaveExitValue(0);
}
- output.shouldNotContain(CDSTestUtils.MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE);
+ //output.shouldNotContain(CDSTestUtils.MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE); // FIXME -- leyden+JEP483 merge
CDSTestUtils.checkCommonExecExceptions(output);
checkExecution(output, runMode);
return output;
}
logToFile(staticArchiveFileLog,
"cds=debug",
"cds+class=debug",
"cds+heap=warning",
"cds+resolve=debug"));
+
return executeAndCheck(cmdLine, runMode, staticArchiveFile, staticArchiveFileLog);
}
// Creating a dynamic CDS archive (with -XX:ArchiveClassesAtExit=<foo>.jsa) requires that the current
// JVM process is using a static archive (which is usually the default CDS archive included in the JDK).
}
cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
return executeAndCheck(cmdLine, runMode, dynamicArchiveFile, dynamicArchiveFileLog);
}
+ private String trainingLog(String file) {
+ return logToFile(file,
+ "cds=debug",
+ "cds+class=debug",
+ "cds+heap=warning",
+ "cds+resolve=debug");
+ }
+
+ // normal training workflow (main JVM process spawns child process)
+ private OutputAnalyzer trainingRun() throws Exception {
+ RunMode runMode = RunMode.TRAINING;
+ File f = new File(cdsFile);
+ f.delete();
+ String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
+ "-XX:+AOTClassLinking",
+ "-XX:+ArchiveDynamicProxies",
+ //"-XX:+ArchiveReflectionData",
+ "-XX:CacheDataStore=" + cdsFile,
+ "-cp", classpath(runMode),
+ // Use PID to distinguish the logs of the training process
+ // and the forked final image dump process.
+ "-Xlog:cds::uptime,level,tags,pid",
+ trainingLog(cdsFileLog));
+ cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
+ OutputAnalyzer out = executeAndCheck(cmdLine, runMode, cdsFile, cdsFileLog);
+ listOutputFile(cdsFile + ".log.0"); // the preimage dump
+ return out;
+ }
+
+ // "split" training workflow (launch the two processes manually, for easier debugging);
+ private OutputAnalyzer trainingRun0() throws Exception {
+ RunMode runMode = RunMode.TRAINING0;
+ File f = new File(cdsFile);
+ f.delete();
+ String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+CDSManualFinalImage",
+ "-XX:+AOTClassLinking",
+ "-XX:+ArchiveDynamicProxies",
+ //"-XX:+ArchiveReflectionData",
+ "-XX:CacheDataStore=" + cdsFile,
+ "-cp", classpath(runMode),
+ trainingLog(cdsFilePreImageLog));
+ cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
+ return executeAndCheck(cmdLine, runMode, cdsFilePreImage, cdsFilePreImageLog);
+ }
+ private OutputAnalyzer trainingRun1() throws Exception {
+ RunMode runMode = RunMode.TRAINING1;
+ File f = new File(cdsFile);
+ f.delete();
+ String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+AOTClassLinking",
+ "-XX:+ArchiveDynamicProxies",
+ //"-XX:+ArchiveReflectionData",
+ "-XX:CacheDataStore=" + cdsFile,
+ "-XX:CDSPreimage=" + cdsFilePreImage,
+ "-cp", classpath(runMode),
+ trainingLog(cdsFileLog));
+ cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
+ return executeAndCheck(cmdLine, runMode, cdsFile, aotFile, cdsFileLog);
+ }
+
private OutputAnalyzer productionRun() throws Exception {
return productionRun(null, null);
}
public OutputAnalyzer productionRun(String[] extraVmArgs) throws Exception {
if (isStaticWorkflow()) {
cmdLine = StringArrayUtils.concat(cmdLine, "-Xshare:on", "-XX:SharedArchiveFile=" + staticArchiveFile);
} else if (isDynamicWorkflow()) {
cmdLine = StringArrayUtils.concat(cmdLine, "-Xshare:on", "-XX:SharedArchiveFile=" + dynamicArchiveFile);
+ } else {
+ cmdLine = StringArrayUtils.concat(cmdLine, "-XX:CacheDataStore=" + cdsFile);
}
if (extraVmArgs != null) {
cmdLine = StringArrayUtils.concat(cmdLine, extraVmArgs);
}
} else {
if (args[0].equals("STATIC")) {
runStaticWorkflow();
} else if (args[0].equals("DYNAMIC")) {
runDynamicWorkflow();
+ } else if (args[0].equals("LEYDEN")) {
+ runLeydenWorkflow(false);
+ } else if (args[0].equals("LEYDEN_TRAINONLY")) {
+ runLeydenWorkflow(true);
} else {
throw new RuntimeException(err);
}
}
}
private void runDynamicWorkflow() throws Exception {
this.workflow = Workflow.DYNAMIC;
dumpDynamicArchive();
productionRun();
}
+
+ private void runLeydenWorkflow(boolean trainOnly) throws Exception {
+ this.workflow = Workflow.LEYDEN;
+ if (System.getProperty("CDSAppTester.split.new.workflow") != null) {
+ trainingRun0();
+ trainingRun1();
+ } else {
+ trainingRun();
+ }
+ if (!trainOnly) {
+ productionRun();
+ }
+ }
}
< prev index next >