< prev index next >

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

Print this page
@@ -33,35 +33,48 @@
  
  /*
   * 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) {

@@ -72,16 +85,20 @@
      }
  
      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;
          }

@@ -124,10 +141,14 @@
  
      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);

@@ -155,11 +176,11 @@
              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;
      }
  

@@ -187,10 +208,11 @@
                                                     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).

@@ -240,10 +262,73 @@
          }
          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 {

@@ -262,10 +347,12 @@
  
          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);
          }

@@ -294,10 +381,14 @@
          } 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);
              }
          }
      }

@@ -312,6 +403,19 @@
      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 >