Fri, 04 Oct 2013 13:44:49 +0200
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
Summary: Adds support for large(>4G) heap dumps in hprof format. Adds tests and updates testlibrary.
Reviewed-by: sla, allwin
Contributed-by: fredrik.arvidsson@oracle.com
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java Fri Oct 04 13:01:07 2013 +0200 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java Fri Oct 04 13:44:49 2013 +0200 1.3 @@ -59,6 +59,7 @@ 1.4 1.5 public boolean doObj(Oop oop) { 1.6 try { 1.7 + writeHeapRecordPrologue(); 1.8 if (oop instanceof TypeArray) { 1.9 writePrimitiveArray((TypeArray)oop); 1.10 } else if (oop instanceof ObjArray) { 1.11 @@ -97,6 +98,7 @@ 1.12 // not-a-Java-visible oop 1.13 writeInternalObject(oop); 1.14 } 1.15 + writeHeapRecordEpilogue(); 1.16 } catch (IOException exp) { 1.17 throw new RuntimeException(exp); 1.18 } 1.19 @@ -416,6 +418,12 @@ 1.20 protected void writeHeapFooter() throws IOException { 1.21 } 1.22 1.23 + protected void writeHeapRecordPrologue() throws IOException { 1.24 + } 1.25 + 1.26 + protected void writeHeapRecordEpilogue() throws IOException { 1.27 + } 1.28 + 1.29 // HeapVisitor, OopVisitor methods can't throw any non-runtime 1.30 // exception. But, derived class write methods (which are called 1.31 // from visitor callbacks) may throw IOException. Hence, we throw
2.1 --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Oct 04 13:01:07 2013 +0200 2.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Oct 04 13:44:49 2013 +0200 2.3 @@ -44,7 +44,7 @@ 2.4 * WARNING: This format is still under development, and is subject to 2.5 * change without notice. 2.6 * 2.7 - * header "JAVA PROFILE 1.0.1" (0-terminated) 2.8 + * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated) 2.9 * u4 size of identifiers. Identifiers are used to represent 2.10 * UTF8 strings, objects, stack traces, etc. They usually 2.11 * have the same size as host pointers. For example, on 2.12 @@ -292,11 +292,34 @@ 2.13 * 0x00000002: cpu sampling on/off 2.14 * u2 stack trace depth 2.15 * 2.16 + * 2.17 + * When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally 2.18 + * be generated as a sequence of heap dump segments. This sequence is 2.19 + * terminated by an end record. The additional tags allowed by format 2.20 + * "JAVA PROFILE 1.0.2" are: 2.21 + * 2.22 + * HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment 2.23 + * 2.24 + * [heap dump sub-records]* 2.25 + * The same sub-record types allowed by HPROF_HEAP_DUMP 2.26 + * 2.27 + * HPROF_HEAP_DUMP_END denotes the end of a heap dump 2.28 + * 2.29 */ 2.30 2.31 public class HeapHprofBinWriter extends AbstractHeapGraphWriter { 2.32 + 2.33 + // The heap size threshold used to determine if segmented format 2.34 + // ("JAVA PROFILE 1.0.2") should be used. 2.35 + private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000; 2.36 + 2.37 + // The approximate size of a heap segment. Used to calculate when to create 2.38 + // a new segment. 2.39 + private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000; 2.40 + 2.41 // hprof binary file header 2.42 - private static final String HPROF_HEADER = "JAVA PROFILE 1.0.1"; 2.43 + private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; 2.44 + private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; 2.45 2.46 // constants in enum HprofTag 2.47 private static final int HPROF_UTF8 = 0x01; 2.48 @@ -312,6 +335,10 @@ 2.49 private static final int HPROF_CPU_SAMPLES = 0x0D; 2.50 private static final int HPROF_CONTROL_SETTINGS = 0x0E; 2.51 2.52 + // 1.0.2 record types 2.53 + private static final int HPROF_HEAP_DUMP_SEGMENT = 0x1C; 2.54 + private static final int HPROF_HEAP_DUMP_END = 0x2C; 2.55 + 2.56 // Heap dump constants 2.57 // constants in enum HprofGcTag 2.58 private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF; 2.59 @@ -352,11 +379,9 @@ 2.60 private static final int JVM_SIGNATURE_ARRAY = '['; 2.61 private static final int JVM_SIGNATURE_CLASS = 'L'; 2.62 2.63 - 2.64 public synchronized void write(String fileName) throws IOException { 2.65 // open file stream and create buffered data output stream 2.66 - FileOutputStream fos = new FileOutputStream(fileName); 2.67 - FileChannel chn = fos.getChannel(); 2.68 + fos = new FileOutputStream(fileName); 2.69 out = new DataOutputStream(new BufferedOutputStream(fos)); 2.70 2.71 VM vm = VM.getVM(); 2.72 @@ -385,6 +410,9 @@ 2.73 FLOAT_SIZE = objectHeap.getFloatSize(); 2.74 DOUBLE_SIZE = objectHeap.getDoubleSize(); 2.75 2.76 + // Check weather we should dump the heap as segments 2.77 + useSegmentedHeapDump = vm.getUniverse().heap().used() > HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD; 2.78 + 2.79 // hprof bin format header 2.80 writeFileHeader(); 2.81 2.82 @@ -394,38 +422,87 @@ 2.83 2.84 // hprof UTF-8 symbols section 2.85 writeSymbols(); 2.86 + 2.87 // HPROF_LOAD_CLASS records for all classes 2.88 writeClasses(); 2.89 2.90 - // write heap data now 2.91 - out.writeByte((byte)HPROF_HEAP_DUMP); 2.92 - out.writeInt(0); // relative timestamp 2.93 - 2.94 - // remember position of dump length, we will fixup 2.95 - // length later - hprof format requires length. 2.96 - out.flush(); 2.97 - long dumpStart = chn.position(); 2.98 - 2.99 - // write dummy length of 0 and we'll fix it later. 2.100 - out.writeInt(0); 2.101 - 2.102 // write CLASS_DUMP records 2.103 writeClassDumpRecords(); 2.104 2.105 // this will write heap data into the buffer stream 2.106 super.write(); 2.107 2.108 + // flush buffer stream. 2.109 + out.flush(); 2.110 + 2.111 + // Fill in final length 2.112 + fillInHeapRecordLength(); 2.113 + 2.114 + if (useSegmentedHeapDump) { 2.115 + // Write heap segment-end record 2.116 + out.writeByte((byte) HPROF_HEAP_DUMP_END); 2.117 + out.writeInt(0); 2.118 + out.writeInt(0); 2.119 + } 2.120 + 2.121 // flush buffer stream and throw it. 2.122 out.flush(); 2.123 out = null; 2.124 2.125 + // close the file stream 2.126 + fos.close(); 2.127 + } 2.128 + 2.129 + @Override 2.130 + protected void writeHeapRecordPrologue() throws IOException { 2.131 + if (currentSegmentStart == 0) { 2.132 + // write heap data header, depending on heap size use segmented heap 2.133 + // format 2.134 + out.writeByte((byte) (useSegmentedHeapDump ? HPROF_HEAP_DUMP_SEGMENT 2.135 + : HPROF_HEAP_DUMP)); 2.136 + out.writeInt(0); 2.137 + 2.138 + // remember position of dump length, we will fixup 2.139 + // length later - hprof format requires length. 2.140 + out.flush(); 2.141 + currentSegmentStart = fos.getChannel().position(); 2.142 + 2.143 + // write dummy length of 0 and we'll fix it later. 2.144 + out.writeInt(0); 2.145 + } 2.146 + } 2.147 + 2.148 + @Override 2.149 + protected void writeHeapRecordEpilogue() throws IOException { 2.150 + if (useSegmentedHeapDump) { 2.151 + out.flush(); 2.152 + if ((fos.getChannel().position() - currentSegmentStart - 4) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) { 2.153 + fillInHeapRecordLength(); 2.154 + currentSegmentStart = 0; 2.155 + } 2.156 + } 2.157 + } 2.158 + 2.159 + private void fillInHeapRecordLength() throws IOException { 2.160 + 2.161 // now get current position to calculate length 2.162 - long dumpEnd = chn.position(); 2.163 + long dumpEnd = fos.getChannel().position(); 2.164 + 2.165 // calculate length of heap data 2.166 - int dumpLen = (int) (dumpEnd - dumpStart - 4); 2.167 + long dumpLenLong = (dumpEnd - currentSegmentStart - 4L); 2.168 + 2.169 + // Check length boundary, overflow could happen but is _very_ unlikely 2.170 + if(dumpLenLong >= (4L * 0x40000000)){ 2.171 + throw new RuntimeException("Heap segment size overflow."); 2.172 + } 2.173 + 2.174 + // Save the current position 2.175 + long currentPosition = fos.getChannel().position(); 2.176 2.177 // seek the position to write length 2.178 - chn.position(dumpStart); 2.179 + fos.getChannel().position(currentSegmentStart); 2.180 + 2.181 + int dumpLen = (int) dumpLenLong; 2.182 2.183 // write length as integer 2.184 fos.write((dumpLen >>> 24) & 0xFF); 2.185 @@ -433,8 +510,8 @@ 2.186 fos.write((dumpLen >>> 8) & 0xFF); 2.187 fos.write((dumpLen >>> 0) & 0xFF); 2.188 2.189 - // close the file stream 2.190 - fos.close(); 2.191 + //Reset to previous current position 2.192 + fos.getChannel().position(currentPosition); 2.193 } 2.194 2.195 private void writeClassDumpRecords() throws IOException { 2.196 @@ -443,7 +520,9 @@ 2.197 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { 2.198 public void visit(Klass k) { 2.199 try { 2.200 + writeHeapRecordPrologue(); 2.201 writeClassDumpRecord(k); 2.202 + writeHeapRecordEpilogue(); 2.203 } catch (IOException e) { 2.204 throw new RuntimeException(e); 2.205 } 2.206 @@ -884,7 +963,12 @@ 2.207 // writes hprof binary file header 2.208 private void writeFileHeader() throws IOException { 2.209 // version string 2.210 - out.writeBytes(HPROF_HEADER); 2.211 + if(useSegmentedHeapDump) { 2.212 + out.writeBytes(HPROF_HEADER_1_0_2); 2.213 + } 2.214 + else { 2.215 + out.writeBytes(HPROF_HEADER_1_0_1); 2.216 + } 2.217 out.writeByte((byte)'\0'); 2.218 2.219 // write identifier size. we use pointers as identifiers. 2.220 @@ -976,6 +1060,7 @@ 2.221 private static final int EMPTY_FRAME_DEPTH = -1; 2.222 2.223 private DataOutputStream out; 2.224 + private FileOutputStream fos; 2.225 private Debugger dbg; 2.226 private ObjectHeap objectHeap; 2.227 private SymbolTable symTbl; 2.228 @@ -983,6 +1068,10 @@ 2.229 // oopSize of the debuggee 2.230 private int OBJ_ID_SIZE; 2.231 2.232 + // Added for hprof file format 1.0.2 support 2.233 + private boolean useSegmentedHeapDump; 2.234 + private long currentSegmentStart; 2.235 + 2.236 private long BOOLEAN_BASE_OFFSET; 2.237 private long BYTE_BASE_OFFSET; 2.238 private long CHAR_BASE_OFFSET; 2.239 @@ -1005,6 +1094,7 @@ 2.240 private static class ClassData { 2.241 int instSize; 2.242 List fields; 2.243 + 2.244 ClassData(int instSize, List fields) { 2.245 this.instSize = instSize; 2.246 this.fields = fields;
3.1 --- a/test/TEST.groups Fri Oct 04 13:01:07 2013 +0200 3.2 +++ b/test/TEST.groups Fri Oct 04 13:44:49 2013 +0200 3.3 @@ -84,7 +84,9 @@ 3.4 runtime/NMT/VirtualAllocTestType.java \ 3.5 runtime/RedefineObject/TestRedefineObject.java \ 3.6 runtime/XCheckJniJsig/XCheckJSig.java \ 3.7 - serviceability/attach/AttachWithStalePidFile.java 3.8 + serviceability/attach/AttachWithStalePidFile.java \ 3.9 + serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 3.10 + 3.11 3.12 # JRE adds further tests to compact3 3.13 #
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java Fri Oct 04 13:44:49 2013 +0200 4.3 @@ -0,0 +1,71 @@ 4.4 +/* 4.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +import java.lang.management.ManagementFactory; 4.28 +import java.lang.management.RuntimeMXBean; 4.29 +import java.lang.reflect.Field; 4.30 +import java.lang.reflect.Method; 4.31 +import java.util.ArrayList; 4.32 +import java.util.List; 4.33 + 4.34 +import sun.management.VMManagement; 4.35 + 4.36 +public class JMapHProfLargeHeapProc { 4.37 + private static final List<byte[]> heapGarbage = new ArrayList<>(); 4.38 + 4.39 + public static void main(String[] args) throws Exception { 4.40 + 4.41 + buildLargeHeap(args); 4.42 + 4.43 + // Print our pid on stdout 4.44 + System.out.println("PID[" + getProcessId() + "]"); 4.45 + 4.46 + // Wait for input before termination 4.47 + System.in.read(); 4.48 + } 4.49 + 4.50 + private static void buildLargeHeap(String[] args) { 4.51 + for (long i = 0; i < Integer.parseInt(args[0]); i++) { 4.52 + heapGarbage.add(new byte[1024]); 4.53 + } 4.54 + } 4.55 + 4.56 + public static int getProcessId() throws Exception { 4.57 + 4.58 + // Get the current process id using a reflection hack 4.59 + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); 4.60 + Field jvm = runtime.getClass().getDeclaredField("jvm"); 4.61 + 4.62 + jvm.setAccessible(true); 4.63 + VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); 4.64 + 4.65 + Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); 4.66 + 4.67 + pid_method.setAccessible(true); 4.68 + 4.69 + int pid = (Integer) pid_method.invoke(mgmt); 4.70 + 4.71 + return pid; 4.72 + } 4.73 + 4.74 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Fri Oct 04 13:44:49 2013 +0200 5.3 @@ -0,0 +1,146 @@ 5.4 +/* 5.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +import java.io.BufferedReader; 5.28 +import java.io.File; 5.29 +import java.io.FileNotFoundException; 5.30 +import java.io.FileReader; 5.31 +import java.io.IOException; 5.32 +import java.io.Reader; 5.33 +import java.nio.CharBuffer; 5.34 +import java.util.Arrays; 5.35 +import java.util.Scanner; 5.36 + 5.37 +import com.oracle.java.testlibrary.Asserts; 5.38 +import com.oracle.java.testlibrary.JDKToolFinder; 5.39 +import com.oracle.java.testlibrary.JDKToolLauncher; 5.40 +import com.oracle.java.testlibrary.OutputAnalyzer; 5.41 +import com.oracle.java.testlibrary.Platform; 5.42 +import com.oracle.java.testlibrary.ProcessTools; 5.43 + 5.44 +/* 5.45 + * @test 5.46 + * @bug 6313383 5.47 + * @key regression 5.48 + * @summary Regression test for hprof export issue due to large heaps (>2G) 5.49 + * @library /testlibrary 5.50 + * @compile JMapHProfLargeHeapProc.java 5.51 + * @run main JMapHProfLargeHeapTest 5.52 + */ 5.53 + 5.54 +public class JMapHProfLargeHeapTest { 5.55 + private static final String HEAP_DUMP_FILE_NAME = "heap.hprof"; 5.56 + private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; 5.57 + private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; 5.58 + private static final long M = 1024L; 5.59 + private static final long G = 1024L * M; 5.60 + 5.61 + public static void main(String[] args) throws Exception { 5.62 + // If we are on MacOSX, test if JMap tool is signed, otherwise return 5.63 + // since test will fail with privilege error. 5.64 + if (Platform.isOSX()) { 5.65 + String jmapToolPath = JDKToolFinder.getCurrentJDKTool("jmap"); 5.66 + ProcessBuilder codesignProcessBuilder = new ProcessBuilder( 5.67 + "codesign", "-v", jmapToolPath); 5.68 + Process codesignProcess = codesignProcessBuilder.start(); 5.69 + OutputAnalyzer analyser = new OutputAnalyzer(codesignProcess); 5.70 + try { 5.71 + analyser.shouldNotContain("code object is not signed at all"); 5.72 + System.out.println("Signed jmap found at: " + jmapToolPath); 5.73 + } catch (Exception e) { 5.74 + // Abort since we can't know if the test will work 5.75 + System.out 5.76 + .println("Test aborted since we are on MacOSX and the jmap tool is not signed."); 5.77 + return; 5.78 + } 5.79 + } 5.80 + 5.81 + // Small heap 22 megabytes, should create 1.0.1 file format 5.82 + testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1); 5.83 + 5.84 + /** 5.85 + * This test was deliberately commented out since the test system lacks 5.86 + * support to handle the requirements for this kind of heap size in a 5.87 + * good way. If or when it becomes possible to run this kind of tests in 5.88 + * the test environment the test should be enabled again. 5.89 + * */ 5.90 + // Large heap 2,2 gigabytes, should create 1.0.2 file format 5.91 + // testHProfFileFormat("-Xmx4g", 2 * G + 2 * M, HPROF_HEADER_1_0_2); 5.92 + } 5.93 + 5.94 + private static void testHProfFileFormat(String vmArgs, long heapSize, 5.95 + String expectedFormat) throws Exception, IOException, 5.96 + InterruptedException, FileNotFoundException { 5.97 + ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder( 5.98 + vmArgs, "JMapHProfLargeHeapProc", String.valueOf(heapSize)); 5.99 + procBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); 5.100 + Process largeHeapProc = procBuilder.start(); 5.101 + 5.102 + try (Scanner largeHeapScanner = new Scanner( 5.103 + largeHeapProc.getInputStream());) { 5.104 + String pidstring = null; 5.105 + while ((pidstring = largeHeapScanner.findInLine("PID\\[[0-9].*\\]")) == null) { 5.106 + Thread.sleep(500); 5.107 + } 5.108 + int pid = Integer.parseInt(pidstring.substring(4, 5.109 + pidstring.length() - 1)); 5.110 + System.out.println("Extracted pid: " + pid); 5.111 + 5.112 + JDKToolLauncher jMapLauncher = JDKToolLauncher 5.113 + .create("jmap", false); 5.114 + jMapLauncher.addToolArg("-dump:format=b,file=" + pid + "-" 5.115 + + HEAP_DUMP_FILE_NAME); 5.116 + jMapLauncher.addToolArg(String.valueOf(pid)); 5.117 + 5.118 + ProcessBuilder jMapProcessBuilder = new ProcessBuilder( 5.119 + jMapLauncher.getCommand()); 5.120 + System.out.println("jmap command: " 5.121 + + Arrays.toString(jMapLauncher.getCommand())); 5.122 + 5.123 + Process jMapProcess = jMapProcessBuilder.start(); 5.124 + OutputAnalyzer analyzer = new OutputAnalyzer(jMapProcess); 5.125 + analyzer.shouldHaveExitValue(0); 5.126 + analyzer.shouldContain(pid + "-" + HEAP_DUMP_FILE_NAME); 5.127 + analyzer.shouldContain("Heap dump file created"); 5.128 + 5.129 + largeHeapProc.getOutputStream().write('\n'); 5.130 + 5.131 + File dumpFile = new File(pid + "-" + HEAP_DUMP_FILE_NAME); 5.132 + Asserts.assertTrue(dumpFile.exists(), "Heap dump file not found."); 5.133 + 5.134 + try (Reader reader = new BufferedReader(new FileReader(dumpFile))) { 5.135 + CharBuffer buf = CharBuffer.allocate(expectedFormat.length()); 5.136 + reader.read(buf); 5.137 + buf.clear(); 5.138 + Asserts.assertEQ(buf.toString(), expectedFormat, 5.139 + "Wrong file format. Expected '" + expectedFormat 5.140 + + "', but found '" + buf.toString() + "'"); 5.141 + } 5.142 + 5.143 + System.out.println("Success!"); 5.144 + 5.145 + } finally { 5.146 + largeHeapProc.destroyForcibly(); 5.147 + } 5.148 + } 5.149 +}
6.1 --- a/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java Fri Oct 04 13:01:07 2013 +0200 6.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java Fri Oct 04 13:44:49 2013 +0200 6.3 @@ -23,20 +23,17 @@ 6.4 6.5 package com.oracle.java.testlibrary; 6.6 6.7 -import java.util.List; 6.8 import java.util.ArrayList; 6.9 import java.util.Arrays; 6.10 - 6.11 -import com.oracle.java.testlibrary.JDKToolFinder; 6.12 -import com.oracle.java.testlibrary.ProcessTools; 6.13 +import java.util.List; 6.14 6.15 /** 6.16 * A utility for constructing command lines for starting JDK tool processes. 6.17 * 6.18 * The JDKToolLauncher can in particular be combined with a 6.19 - * java.lang.ProcessBuilder to easily run a JDK tool. For example, the 6.20 - * following code run {@code jmap -heap} against a process with GC logging 6.21 - * turned on for the {@code jmap} process: 6.22 + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following 6.23 + * code run {@code jmap -heap} against a process with GC logging turned on for 6.24 + * the {@code jmap} process: 6.25 * 6.26 * <pre> 6.27 * {@code 6.28 @@ -55,19 +52,39 @@ 6.29 private final List<String> vmArgs = new ArrayList<String>(); 6.30 private final List<String> toolArgs = new ArrayList<String>(); 6.31 6.32 - private JDKToolLauncher(String tool) { 6.33 - executable = JDKToolFinder.getJDKTool(tool); 6.34 + private JDKToolLauncher(String tool, boolean useCompilerJDK) { 6.35 + if (useCompilerJDK) { 6.36 + executable = JDKToolFinder.getJDKTool(tool); 6.37 + } else { 6.38 + executable = JDKToolFinder.getCurrentJDKTool(tool); 6.39 + } 6.40 vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs())); 6.41 } 6.42 6.43 /** 6.44 + * Creates a new JDKToolLauncher for the specified tool. Using tools path 6.45 + * from the compiler JDK. 6.46 + * 6.47 + * @param tool 6.48 + * The name of the tool 6.49 + * @return A new JDKToolLauncher 6.50 + */ 6.51 + public static JDKToolLauncher create(String tool) { 6.52 + return new JDKToolLauncher(tool, true); 6.53 + } 6.54 + 6.55 + /** 6.56 * Creates a new JDKToolLauncher for the specified tool. 6.57 * 6.58 - * @param tool The name of the tool 6.59 + * @param tool 6.60 + * The name of the tool 6.61 + * @param useCompilerPath 6.62 + * If true use the compiler JDK path, otherwise use the tested 6.63 + * JDK path. 6.64 * @return A new JDKToolLauncher 6.65 */ 6.66 - public static JDKToolLauncher create(String tool) { 6.67 - return new JDKToolLauncher(tool); 6.68 + public static JDKToolLauncher create(String tool, boolean useCompilerJDK) { 6.69 + return new JDKToolLauncher(tool, useCompilerJDK); 6.70 } 6.71 6.72 /** 6.73 @@ -80,7 +97,8 @@ 6.74 * automatically added. 6.75 * 6.76 * 6.77 - * @param arg The argument to VM running the tool 6.78 + * @param arg 6.79 + * The argument to VM running the tool 6.80 * @return The JDKToolLauncher instance 6.81 */ 6.82 public JDKToolLauncher addVMArg(String arg) { 6.83 @@ -91,7 +109,8 @@ 6.84 /** 6.85 * Adds an argument to the tool. 6.86 * 6.87 - * @param arg The argument to the tool 6.88 + * @param arg 6.89 + * The argument to the tool 6.90 * @return The JDKToolLauncher instance 6.91 */ 6.92 public JDKToolLauncher addToolArg(String arg) {