1 /* 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * Helper superclass for launching JDI tests out of the CDS archive. 26 */ 27 28 import jdk.test.lib.process.OutputAnalyzer; 29 import jdk.test.lib.process.ProcessTools; 30 31 import java.io.*; 32 import java.util.ArrayList; 33 import sun.tools.jar.Main; 34 35 public class CDSJDITest { 36 private static final String classesDir = System.getProperty("test.classes"); 37 38 public static void runTest(String testname, String[] jarClasses) throws Exception { 39 File jarClasslistFile = makeClassList(jarClasses); 40 String appJar = buildJar(testname, jarClasses); 41 42 // These are the arguments passed to createJavaProcessBuilder() to launch 43 // the JDI test. 44 String[] testArgs = { 45 // JVM Args: 46 // These first three properties are setup by jtreg, and must be passed 47 // to the JDI test subprocess because it needs them in order to 48 // pass them to the subprocess it will create for the debuggee. This 49 // is how the JPRT -javaopts are passed to the debggee. See 50 // VMConnection.getDebuggeeVMOptions(). 51 getPropOpt("test.classes"), 52 getPropOpt("test.java.opts"), 53 getPropOpt("test.vm.opts"), 54 // Pass -showversion to the JDI test just so we get a bit of trace output. 55 "-showversion", 56 // Main class: 57 testname, 58 // Args to the Main Class: 59 // These argument all follow the above <testname> argument, and are 60 // in fact passed to <testname>.main() as java arguments. <testname> will 61 // pass them as JVM arguments to the debuggee process it creates. 62 "-Xbootclasspath/a:" + appJar, 63 "-XX:+UnlockDiagnosticVMOptions", 64 "-XX:+TraceClassPaths", 65 "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", 66 "-Xshare:on", 67 "-showversion" 68 }; 69 70 // Dump the archive 71 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 72 "-Xbootclasspath/a:" + appJar, 73 "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", 74 "-XX:ExtraSharedClassListFile=" + jarClasslistFile.getPath(), 75 "-Xshare:dump"); 76 OutputAnalyzer outputDump = executeAndLog(pb, "exec"); 77 for (String jarClass : jarClasses) { 78 outputDump.shouldNotContain("Cannot find " + jarClass); 79 } 80 outputDump.shouldContain("Loading classes to share"); 81 outputDump.shouldHaveExitValue(0); 82 83 // Run the test specified JDI test 84 pb = ProcessTools.createJavaProcessBuilder(true, testArgs); 85 OutputAnalyzer outputRun = executeAndLog(pb, "exec"); 86 try { 87 outputRun.shouldContain("sharing"); 88 outputRun.shouldHaveExitValue(0); 89 } catch (RuntimeException e) { 90 outputRun.shouldContain("Unable to use shared archive"); 91 outputRun.shouldHaveExitValue(1); 92 } 93 } 94 95 public static String getPropOpt(String prop) { 96 String propVal = System.getProperty(prop); 97 if (propVal == null) propVal = ""; 98 System.out.println(prop + ": '" + propVal + "'"); 99 return "-D" + prop + "=" + propVal; 100 } 101 102 public static File makeClassList(String appClasses[]) throws Exception { 103 File classList = getOutputFile("test.classlist"); 104 FileOutputStream fos = new FileOutputStream(classList); 105 PrintStream ps = new PrintStream(fos); 106 107 addToClassList(ps, appClasses); 108 109 ps.close(); 110 fos.close(); 111 112 return classList; 113 } 114 115 public static OutputAnalyzer executeAndLog(ProcessBuilder pb, String logName) throws Exception { 116 long started = System.currentTimeMillis(); 117 OutputAnalyzer output = ProcessTools.executeProcess(pb); 118 writeFile(getOutputFile(logName + ".stdout"), output.getStdout()); 119 writeFile(getOutputFile(logName + ".stderr"), output.getStderr()); 120 System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]"); 121 System.out.println("[STDOUT]\n" + output.getStdout()); 122 System.out.println("[STDERR]\n" + output.getStderr()); 123 return output; 124 } 125 126 private static void writeFile(File file, String content) throws Exception { 127 FileOutputStream fos = new FileOutputStream(file); 128 PrintStream ps = new PrintStream(fos); 129 ps.print(content); 130 ps.close(); 131 fos.close(); 132 } 133 134 public static File getOutputFile(String name) { 135 File dir = new File(System.getProperty("test.classes", ".")); 136 return new File(dir, getTestNamePrefix() + name); 137 } 138 139 private static void addToClassList(PrintStream ps, String classes[]) throws IOException { 140 if (classes != null) { 141 for (String s : classes) { 142 ps.println(s); 143 } 144 } 145 } 146 147 private static String testNamePrefix; 148 149 private static String getTestNamePrefix() { 150 if (testNamePrefix == null) { 151 StackTraceElement[] elms = (new Throwable()).getStackTrace(); 152 if (elms.length > 0) { 153 for (StackTraceElement n: elms) { 154 if ("main".equals(n.getMethodName())) { 155 testNamePrefix = n.getClassName() + "-"; 156 break; 157 } 158 } 159 } 160 161 if (testNamePrefix == null) { 162 testNamePrefix = ""; 163 } 164 } 165 return testNamePrefix; 166 } 167 168 private static String buildJar(String jarName, String ...classNames) 169 throws Exception { 170 171 String jarFullName = classesDir + File.separator + jarName + ".jar"; 172 createSimpleJar(classesDir, jarFullName, classNames); 173 return jarFullName; 174 } 175 176 private static void createSimpleJar(String jarClassesDir, String jarName, 177 String[] classNames) throws Exception { 178 179 ArrayList<String> args = new ArrayList<String>(); 180 args.add("cf"); 181 args.add(jarName); 182 addJarClassArgs(args, jarClassesDir, classNames); 183 createJar(args); 184 } 185 186 private static void addJarClassArgs(ArrayList<String> args, String jarClassesDir, 187 String[] classNames) { 188 189 for (String name : classNames) { 190 args.add("-C"); 191 args.add(jarClassesDir); 192 args.add(name + ".class"); 193 } 194 } 195 196 private static void createJar(ArrayList<String> args) { 197 Main jarTool = new Main(System.out, System.err, "jar"); 198 if (!jarTool.run(args.toArray(new String[1]))) { 199 throw new RuntimeException("jar operation failed"); 200 } 201 } 202 }