< prev index next >

test/lib/jdk/test/lib/cds/CDSAppTester.java

Print this page
@@ -31,20 +31,31 @@
  
  /*
   * 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 productionRunLog;
+     private final String codeCacheFile;  // old workflow
+     private final String codeCacheFileLog;
+     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"
  
      public CDSAppTester(String name) {
          // Old workflow
          this.name = name;
          classListFile = name() + ".classlist";

@@ -52,21 +63,35 @@
          staticArchiveFile = name() + ".static.jsa";
          staticArchiveFileLog = staticArchiveFile + ".log";
          dynamicArchiveFile = name() + ".dynamic.jsa";
          dynamicArchiveFileLog = dynamicArchiveFile + ".log";
          productionRunLog = name() + ".production.log";
+ 
+         codeCacheFile = name() + ".code.jsa";
+         codeCacheFileLog = codeCacheFile + ".log";
+         cdsFile = name() + ".cds";
+         cdsFileLog = cdsFile + ".log";
+         cdsFilePreImage = cdsFile + ".preimage";
+         cdsFilePreImageLog = cdsFilePreImage + ".log";
+         aotFile = cdsFile + ".code";
      }
  
      private enum Workflow {
          STATIC,        // classic -Xshare:dump workflow
          DYNAMIC,       // classic -XX:ArchiveClassesAtExit
+         LEYDEN_OLD,    // The old "5 step workflow", to be phased out
+         LEYDEN,        // The new "one step training workflow" -- see JDK-8320264
      }
  
      public enum RunMode {
          CLASSLIST,
          DUMP_STATIC,
          DUMP_DYNAMIC,
+         DUMP_CODECACHE,    // LEYDEN_OLD only
+         TRAINING,          // LEYDEN only
+         TRAINING0,         // LEYDEN only
+         TRAINING1,         // LEYDEN only
          PRODUCTION;
  
          public boolean isStaticDump() {
              return this == DUMP_STATIC;
          }

@@ -95,19 +120,32 @@
  
      // optional
      public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {}
  
      private Workflow workflow;
+     private boolean checkExitValue = true;
+ 
+     public final void setCheckExitValue(boolean b) {
+         checkExitValue = b;
+     }
  
      public final boolean isStaticWorkflow() {
          return workflow == Workflow.STATIC;
      }
  
      public final boolean isDynamicWorkflow() {
          return workflow == Workflow.DYNAMIC;
      }
  
+     public final boolean isLeydenOldWorkflow() {
+         return workflow == Workflow.LEYDEN_OLD;
+     }
+ 
+     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);

@@ -132,11 +170,13 @@
          Process process = pb.start();
          OutputAnalyzer output = CDSTestUtils.executeAndLog(process, runMode.toString());
          for (String logFile : logFiles) {
              listOutputFile(logFile);
          }
-         output.shouldHaveExitValue(0);
+         if (checkExitValue) {
+             output.shouldHaveExitValue(0);
+         }
          CDSTestUtils.checkCommonExecExceptions(output);
          checkExecution(output, runMode);
          return output;
      }
  

@@ -164,10 +204,18 @@
                                                     logToFile(staticArchiveFileLog,
                                                               "cds=debug",
                                                               "cds+class=debug",
                                                               "cds+heap=warning",
                                                               "cds+resolve=debug"));
+         if (isLeydenOldWorkflow()) {
+             cmdLine = StringArrayUtils.concat(cmdLine,
+                                               "-XX:+PreloadSharedClasses",
+                                               "-XX:+ArchiveInvokeDynamic",
+                                               "-XX:+ArchiveDynamicProxies",
+                                               "-XX:+ArchiveReflectionData");
+         }
+ 
          return executeAndCheck(cmdLine, runMode, staticArchiveFile, staticArchiveFileLog);
      }
  
      private OutputAnalyzer dumpDynamicArchive() throws Exception {
          RunMode runMode = RunMode.DUMP_DYNAMIC;

@@ -181,25 +229,135 @@
                                              logToFile(dynamicArchiveFileLog,
                                                        "cds=debug",
                                                        "cds+class=debug",
                                                        "cds+resolve=debug",
                                                        "class+load=debug"));
+         } else {
+           // Leyden "OLD" workflow step 3
+           cmdLine = StringArrayUtils.concat(vmArgs(runMode),
+                                             "-Xlog:cds",
+                                             "-XX:ArchiveClassesAtExit=" + dynamicArchiveFile,
+                                             "-XX:SharedArchiveFile=" + staticArchiveFile,
+                                             "-XX:+RecordTraining",
+                                             "-cp", classpath(runMode),
+                                             logToFile(dynamicArchiveFileLog,
+                                                       "cds=debug",
+                                                       "cds+class=debug",
+                                                       "cds+resolve=debug",
+                                                       "class+load=debug"));
          }
          cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
          return executeAndCheck(cmdLine, runMode, dynamicArchiveFile, dynamicArchiveFileLog);
      }
  
+ 
+     private OutputAnalyzer dumpCodeCache() throws Exception {
+         RunMode runMode = RunMode.DUMP_CODECACHE;
+         String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
+                                                    "-XX:SharedArchiveFile=" + dynamicArchiveFile,
+                                                    "-XX:+ReplayTraining",
+                                                    "-XX:+StoreCachedCode",
+                                                    "-XX:CachedCodeFile=" + codeCacheFile,
+                                                    "-XX:CachedCodeMaxSize=512M",
+                                                    "-cp", classpath(runMode),
+                                                    logToFile(codeCacheFileLog, "scc"));
+ 
+         cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
+         return executeAndCheck(cmdLine, runMode, codeCacheFile, codeCacheFileLog);
+     }
+ 
+     private OutputAnalyzer oldProductionRun() throws Exception {
+         RunMode runMode = RunMode.PRODUCTION;
+         String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
+                                                    "-XX:SharedArchiveFile=" + dynamicArchiveFile,
+                                                    "-XX:+ReplayTraining",
+                                                    "-XX:+LoadCachedCode",
+                                                    "-XX:CachedCodeFile=" + codeCacheFile,
+                                                    "-cp", classpath(runMode),
+                                                    logToFile(productionRunLog, "cds", "scc*=warning"));
+         cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
+         return executeAndCheck(cmdLine, runMode, productionRunLog);
+     }
+ 
+     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:+PreloadSharedClasses",
+                                                    "-XX:+ArchiveInvokeDynamic",
+                                                    "-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:+PreloadSharedClasses",
+                                                    "-XX:+ArchiveInvokeDynamic",
+                                                    "-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:+PreloadSharedClasses",
+                                                    "-XX:+ArchiveInvokeDynamic",
+                                                    "-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 {
          RunMode runMode = RunMode.PRODUCTION;
          String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
                                                     "-cp", classpath(runMode),
                                                     logToFile(productionRunLog, "cds"));
  
          if (isStaticWorkflow()) {
              cmdLine = StringArrayUtils.concat(cmdLine, "-XX:SharedArchiveFile=" + staticArchiveFile);
          } else if (isDynamicWorkflow()) {
              cmdLine = StringArrayUtils.concat(cmdLine, "-XX:SharedArchiveFile=" + dynamicArchiveFile);
+         } else {
+             cmdLine = StringArrayUtils.concat(cmdLine, "-XX:CacheDataStore=" + cdsFile);
          }
  
          cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode));
          return executeAndCheck(cmdLine, runMode, productionRunLog);
      }

@@ -217,10 +375,16 @@
          } else {
              if (args[0].equals("STATIC")) {
                  runStaticWorkflow();
              } else if (args[0].equals("DYNAMIC")) {
                  runDynamicWorkflow();
+             } else if (args[0].equals("LEYDEN_OLD")) {
+                 runLeydenOldWorkflow();
+             } else if (args[0].equals("LEYDEN")) {
+                 runLeydenWorkflow(false);
+             } else if (args[0].equals("LEYDEN_TRAINONLY")) {
+                 runLeydenWorkflow(true);
              } else {
                  throw new RuntimeException(err);
              }
          }
      }

@@ -235,6 +399,28 @@
      private void runDynamicWorkflow() throws Exception {
          this.workflow = Workflow.DYNAMIC;
          dumpDynamicArchive();
          productionRun();
      }
+ 
+     private void runLeydenOldWorkflow() throws Exception {
+         this.workflow = Workflow.LEYDEN_OLD;
+         createClassList();
+         dumpStaticArchive();
+         dumpDynamicArchive();
+         dumpCodeCache();
+         oldProductionRun();
+     }
+ 
+     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 >