# HG changeset patch # User miauno # Date 1422444415 -3600 # Node ID 6b375d035178b00f3ceda31e5efc93db61460ecf # Parent 080a0772cf9527522dc05698f0d69f8183529359 8071909: Port testlibrary improvments in jdk/test to hotspot/test as required for DCMD test port Reviewed-by: diff --git a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java --- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java @@ -24,6 +24,8 @@ package com.oracle.java.testlibrary; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -69,6 +71,58 @@ } /** + * Verify that the stdout contents of output buffer is empty + * + * @throws RuntimeException + * If stdout was not empty + */ + public void stdoutShouldBeEmpty() { + if (!getStdout().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was not empty"); + } + } + + /** + * Verify that the stderr contents of output buffer is empty + * + * @throws RuntimeException + * If stderr was not empty + */ + public void stderrShouldBeEmpty() { + if (!getStderr().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was not empty"); + } + } + + /** + * Verify that the stdout contents of output buffer is not empty + * + * @throws RuntimeException + * If stdout was empty + */ + public void stdoutShouldNotBeEmpty() { + if (getStdout().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was empty"); + } + } + + /** + * Verify that the stderr contents of output buffer is not empty + * + * @throws RuntimeException + * If stderr was empty + */ + public void stderrShouldNotBeEmpty() { + if (getStderr().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was empty"); + } + } + + /** * Verify that the stdout and stderr contents of output buffer contains the string * * @param expectedString String that buffer should contain @@ -365,4 +419,23 @@ public int getExitValue() { return exitValue; } + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by system property 'line.separator'. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + return asLines(getOutput()); + } + + private List asLines(String buffer) { + List l = new ArrayList<>(); + String[] a = buffer.split(Utils.NEW_LINE); + for (String string : a) { + l.add(string); + } + return l; + } } diff --git a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java --- a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java @@ -184,23 +184,36 @@ return executeProcess(pb); } - /** - * Executes a process, waits for it to finish and returns the process output. - * @param pb The ProcessBuilder to execute. - * @return The output from the process. - */ - public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable { - OutputAnalyzer output = null; - try { - output = new OutputAnalyzer(pb.start()); - return output; - } catch (Throwable t) { - System.out.println("executeProcess() failed: " + t); - throw t; - } finally { - System.out.println(getProcessLog(pb, output)); + /** + * Executes a process, waits for it to finish and returns the process output. + * The process will have exited before this method returns. + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = null; + Process p = null; + boolean failed = false; + try { + p = pb.start(); + output = new OutputAnalyzer(p); + p.waitFor(); + + return output; + } catch (Throwable t) { + if (p != null) { + p.destroyForcibly().waitFor(); + } + + failed = true; + System.out.println("executeProcess() failed: " + t); + throw t; + } finally { + if (failed) { + System.err.println(getProcessLog(pb, output)); + } + } } - } /** * Executes a process, waits for it to finish and returns the process output. # HG changeset patch # User miauno # Date 1422539382 -3600 # Node ID 9c2352d651ef1c5ee86f1644b1f87e62b29aa79b # Parent 6b375d035178b00f3ceda31e5efc93db61460ecf 8071908: Port internal Diagnostic Command tests and test framework to jtreg Reviewed-by: diff --git a/test/TEST.groups b/test/TEST.groups --- a/test/TEST.groups +++ b/test/TEST.groups @@ -97,7 +97,7 @@ runtime/XCheckJniJsig/XCheckJSig.java \ serviceability/attach/AttachWithStalePidFile.java \ serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \ - serviceability/dcmd/DynLibDcmdTest.java + serviceability/dcmd/vm/DynLibsTest.java # JRE adds further tests to compact3 diff --git a/test/serviceability/dcmd/ClassLoaderStatsTest.java b/test/serviceability/dcmd/ClassLoaderStatsTest.java deleted file mode 100644 --- a/test/serviceability/dcmd/ClassLoaderStatsTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * - * @build ClassLoaderStatsTest DcmdUtil - * @run main ClassLoaderStatsTest - */ - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.StringReader; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ClassLoaderStatsTest { - - // ClassLoader Parent CLD* Classes ChunkSz BlockSz Type - // 0x00000007c0215928 0x0000000000000000 0x0000000000000000 0 0 0 org.eclipse.osgi.baseadaptor.BaseAdaptor$1 - // 0x00000007c0009868 0x0000000000000000 0x00007fc52aebcc80 1 6144 3768 sun.reflect.DelegatingClassLoader - // 0x00000007c0009868 0x0000000000000000 0x00007fc52b8916d0 1 6144 3688 sun.reflect.DelegatingClassLoader - // 0x00000007c0009868 0x00000007c0038ba8 0x00007fc52afb8760 1 6144 3688 sun.reflect.DelegatingClassLoader - // 0x00000007c0009868 0x0000000000000000 0x00007fc52afbb1a0 1 6144 3688 sun.reflect.DelegatingClassLoader - // 0x0000000000000000 0x0000000000000000 0x00007fc523416070 5019 30060544 29956216 - // 455 1210368 672848 + unsafe anonymous classes - // 0x00000007c016b5c8 0x00000007c0038ba8 0x00007fc52a995000 5 8192 5864 org.netbeans.StandardModule$OneModuleClassLoader - // 0x00000007c0009868 0x00000007c016b5c8 0x00007fc52ac13640 1 6144 3896 sun.reflect.DelegatingClassLoader - // ... - - static Pattern clLine = Pattern.compile("0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(.*)"); - static Pattern anonLine = Pattern.compile("\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*.*"); - - public static DummyClassLoader dummyloader; - - public static void main(String arg[]) throws Exception { - - // create a classloader and load our special class - dummyloader = new DummyClassLoader(); - Class c = Class.forName("TestClass", true, dummyloader); - if (c.getClassLoader() != dummyloader) { - throw new RuntimeException("TestClass defined by wrong classloader: " + c.getClassLoader()); - } - - String result = DcmdUtil.executeDcmd("VM.classloader_stats"); - BufferedReader r = new BufferedReader(new StringReader(result)); - String line; - while((line = r.readLine()) != null) { - Matcher m = clLine.matcher(line); - if (m.matches()) { - // verify that DummyClassLoader has loaded 1 class and 1 anonymous class - if (m.group(4).equals("ClassLoaderStatsTest$DummyClassLoader")) { - System.out.println("line: " + line); - if (!m.group(1).equals("1")) { - throw new Exception("Should have loaded 1 class: " + line); - } - checkPositiveInt(m.group(2)); - checkPositiveInt(m.group(3)); - - String next = r.readLine(); - System.out.println("next: " + next); - Matcher m1 = anonLine.matcher(next); - m1.matches(); - if (!m1.group(1).equals("1")) { - throw new Exception("Should have loaded 1 anonymous class, but found : " + m1.group(1)); - } - checkPositiveInt(m1.group(2)); - checkPositiveInt(m1.group(3)); - } - } - } - } - - private static void checkPositiveInt(String s) throws Exception { - if (Integer.parseInt(s) <= 0) { - throw new Exception("Value should have been > 0: " + s); - } - } - - public static class DummyClassLoader extends ClassLoader { - - public static final String CLASS_NAME = "TestClass"; - - static ByteBuffer readClassFile(String name) - { - File f = new File(System.getProperty("test.classes", "."), - name); - try (FileInputStream fin = new FileInputStream(f); - FileChannel fc = fin.getChannel()) - { - return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); - } catch (IOException e) { - throw new RuntimeException("Can't open file: " + name, e); - } - } - - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException - { - Class c; - if (!"TestClass".equals(name)) { - c = super.loadClass(name, resolve); - } else { - // should not delegate to the system class loader - c = findClass(name); - if (resolve) { - resolveClass(c); - } - } - return c; - } - - protected Class findClass(String name) - throws ClassNotFoundException - { - if (!"TestClass".equals(name)) { - throw new ClassNotFoundException("Unexpected class: " + name); - } - return defineClass(name, readClassFile(name + ".class"), null); - } - } /* DummyClassLoader */ - -} - -class TestClass { - static { - // force creation of anonymous class (for the lambdaform) - Runnable r = () -> System.out.println("Hello"); - r.run(); - } -} diff --git a/test/serviceability/dcmd/DcmdUtil.java b/test/serviceability/dcmd/DcmdUtil.java deleted file mode 100644 --- a/test/serviceability/dcmd/DcmdUtil.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import sun.management.ManagementFactoryHelper; - -import com.sun.management.DiagnosticCommandMBean; - -public class DcmdUtil -{ - public static String executeDcmd(String cmd, String ... args) { - DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean(); - Object[] dcmdArgs = {args}; - String[] signature = {String[].class.getName()}; - - try { - System.out.print("> " + cmd + " "); - for (String s : args) { - System.out.print(s + " "); - } - System.out.println(":"); - String result = (String) dcmd.invoke(transform(cmd), dcmdArgs, signature); - System.out.println(result); - return result; - } catch(Exception ex) { - ex.printStackTrace(); - } - return null; - } - - private static String transform(String name) { - StringBuilder sb = new StringBuilder(); - boolean toLower = true; - boolean toUpper = false; - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (c == '.' || c == '_') { - toLower = false; - toUpper = true; - } else { - if (toUpper) { - toUpper = false; - sb.append(Character.toUpperCase(c)); - } else if(toLower) { - sb.append(Character.toLowerCase(c)); - } else { - sb.append(c); - } - } - } - return sb.toString(); - } - -} diff --git a/test/serviceability/dcmd/DynLibDcmdTest.java b/test/serviceability/dcmd/DynLibDcmdTest.java deleted file mode 100644 --- a/test/serviceability/dcmd/DynLibDcmdTest.java +++ /dev/null @@ -1,69 +0,0 @@ -import java.util.HashSet; -import java.util.Set; -import com.oracle.java.testlibrary.Platform; - -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test of VM.dynlib diagnostic command via MBean - * @library /testlibrary - * @build com.oracle.java.testlibrary.* DcmdUtil - * @run main DynLibDcmdTest - */ - -public class DynLibDcmdTest { - - public static void main(String[] args) throws Exception { - String result = DcmdUtil.executeDcmd("VM.dynlibs"); - - String osDependentBaseString = null; - if (Platform.isAix()) { - osDependentBaseString = "lib%s.so"; - } else if (Platform.isLinux()) { - osDependentBaseString = "lib%s.so"; - } else if (Platform.isOSX()) { - osDependentBaseString = "lib%s.dylib"; - } else if (Platform.isSolaris()) { - osDependentBaseString = "lib%s.so"; - } else if (Platform.isWindows()) { - osDependentBaseString = "%s.dll"; - } - - if (osDependentBaseString == null) { - throw new Exception("Unsupported OS"); - } - - Set expectedContent = new HashSet<>(); - expectedContent.add(String.format(osDependentBaseString, "jvm")); - expectedContent.add(String.format(osDependentBaseString, "java")); - expectedContent.add(String.format(osDependentBaseString, "management")); - - for(String expected : expectedContent) { - if (!result.contains(expected)) { - throw new Exception("Dynamic library list output did not contain the expected string: '" + expected + "'"); - } - } - } -} diff --git a/test/serviceability/dcmd/compiler/CodeCacheTest.java b/test/serviceability/dcmd/compiler/CodeCacheTest.java --- a/test/serviceability/dcmd/compiler/CodeCacheTest.java +++ b/test/serviceability/dcmd/compiler/CodeCacheTest.java @@ -24,17 +24,21 @@ /* * @test CodeCacheTest * @bug 8054889 - * @library .. - * @build DcmdUtil CodeCacheTest - * @run main/othervm -XX:+SegmentedCodeCache CodeCacheTest - * @run main/othervm -XX:-SegmentedCodeCache CodeCacheTest - * @run main/othervm -Xint -XX:+SegmentedCodeCache CodeCacheTest + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng/othervm -XX:+SegmentedCodeCache CodeCacheTest + * @run testng/othervm -XX:-SegmentedCodeCache CodeCacheTest + * @run testng/othervm -Xint -XX:+SegmentedCodeCache CodeCacheTest * @summary Test of diagnostic command Compiler.codecache */ -import java.io.BufferedReader; -import java.io.StringReader; -import java.lang.reflect.Method; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -86,10 +90,10 @@ return Integer.parseInt(match.substring(match.lastIndexOf(" ") + 1, match.length())); } - public static void main(String arg[]) throws Exception { + public void run(CommandExecutor executor) { // Get number of code cache segments int segmentsCount = 0; - String flags = DcmdUtil.executeDcmd("VM.flags", "-all"); + String flags = executor.execute("VM.flags -all").getOutput(); if (!getFlagBool("SegmentedCodeCache", flags) || !getFlagBool("UseCompiler", flags)) { // No segmentation segmentsCount = 1; @@ -102,29 +106,29 @@ } // Get output from dcmd (diagnostic command) - String result = DcmdUtil.executeDcmd("Compiler.codecache"); - BufferedReader r = new BufferedReader(new StringReader(result)); + OutputAnalyzer output = executor.execute("Compiler.codecache"); + Iterator lines = output.asLines().iterator(); // Validate code cache segments String line; Matcher m; for (int s = 0; s < segmentsCount; ++s) { // Validate first line - line = r.readLine(); + line = lines.next(); m = line1.matcher(line); if (m.matches()) { for (int i = 2; i <= 5; i++) { int val = Integer.parseInt(m.group(i)); if (val < 0) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } } } else { - throw new Exception("Regexp 1 failed"); + throw new RuntimeException("Regexp 1 failed"); } // Validate second line - line = r.readLine(); + line = lines.next(); m = line2.matcher(line); if (m.matches()) { String start = m.group(1); @@ -133,44 +137,49 @@ // Lexical compare of hex numbers to check that they look sane. if (start.compareTo(mark) > 1) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } if (mark.compareTo(top) > 1) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } } else { - throw new Exception("Regexp 2 failed line: " + line); + throw new RuntimeException("Regexp 2 failed line: " + line); } } // Validate third line - line = r.readLine(); + line = lines.next(); m = line3.matcher(line); if (m.matches()) { int blobs = Integer.parseInt(m.group(1)); if (blobs <= 0) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } int nmethods = Integer.parseInt(m.group(2)); if (nmethods < 0) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } int adapters = Integer.parseInt(m.group(3)); if (adapters <= 0) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } if (blobs < (nmethods + adapters)) { - throw new Exception("Failed parsing dcmd codecache output"); + throw new RuntimeException("Failed parsing dcmd codecache output"); } } else { - throw new Exception("Regexp 3 failed"); + throw new RuntimeException("Regexp 3 failed"); } // Validate fourth line - line = r.readLine(); + line = lines.next(); m = line4.matcher(line); if (!m.matches()) { - throw new Exception("Regexp 4 failed"); + throw new RuntimeException("Regexp 4 failed"); } } + + @Test + public void jmx() { + run(new JMXExecutor()); + } } diff --git a/test/serviceability/dcmd/compiler/CodelistTest.java b/test/serviceability/dcmd/compiler/CodelistTest.java --- a/test/serviceability/dcmd/compiler/CodelistTest.java +++ b/test/serviceability/dcmd/compiler/CodelistTest.java @@ -24,15 +24,23 @@ /* * @test CodelistTest * @bug 8054889 - * @library .. - * @build DcmdUtil MethodIdentifierParser CodelistTest - * @run main CodelistTest + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @build MethodIdentifierParser + * @run testng CodelistTest * @summary Test of diagnostic command Compiler.codelist */ +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + import java.io.BufferedReader; import java.io.StringReader; import java.lang.reflect.Method; +import java.util.Iterator; public class CodelistTest { @@ -51,19 +59,18 @@ * */ - public static void main(String arg[]) throws Exception { + public void run(CommandExecutor executor) { int ok = 0; int fail = 0; // Get output from dcmd (diagnostic command) - String result = DcmdUtil.executeDcmd("Compiler.codelist"); - BufferedReader r = new BufferedReader(new StringReader(result)); + OutputAnalyzer output = executor.execute("Compiler.codelist"); + //Iterator lines = output.asLines().iterator(); // Grab a method name from the output - String line; int count = 0; - while((line = r.readLine()) != null) { + for (String line : output.asLines()) { count++; String[] parts = line.split(" "); @@ -88,9 +95,11 @@ m = mf.getMethod(); } catch (NoSuchMethodException e) { m = null; + } catch (ClassNotFoundException e) { + throw new RuntimeException("Test error: Caught unexpected exception", e); } if (m == null) { - throw new Exception("Test failed on: " + methodPrintedInLogFormat); + throw new RuntimeException("Test failed on: " + methodPrintedInLogFormat); } if (count > 10) { // Testing 10 entries is enough. Lets not waste time. @@ -98,4 +107,9 @@ } } } + + @Test + public void jmx() { + run(new JMXExecutor()); + } } diff --git a/test/serviceability/dcmd/compiler/CompilerQueueTest.java b/test/serviceability/dcmd/compiler/CompilerQueueTest.java --- a/test/serviceability/dcmd/compiler/CompilerQueueTest.java +++ b/test/serviceability/dcmd/compiler/CompilerQueueTest.java @@ -24,17 +24,22 @@ /* * @test CompilerQueueTest * @bug 8054889 - * @library .. + * @library /testlibrary * @ignore 8069160 - * @build DcmdUtil CompilerQueueTest - * @run main CompilerQueueTest - * @run main/othervm -XX:-TieredCompilation CompilerQueueTest - * @run main/othervm -Xint CompilerQueueTest + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng CompilerQueueTest + * @run testng/othervm -XX:-TieredCompilation CompilerQueueTest + * @run testng/othervm -Xint CompilerQueueTest * @summary Test of diagnostic command Compiler.queue */ -import java.io.BufferedReader; -import java.io.StringReader; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +import java.util.Iterator; public class CompilerQueueTest { @@ -60,52 +65,55 @@ * **/ - public static void main(String arg[]) throws Exception { + public void run(CommandExecutor executor) { // Get output from dcmd (diagnostic command) - String result = DcmdUtil.executeDcmd("Compiler.queue"); - BufferedReader r = new BufferedReader(new StringReader(result)); + OutputAnalyzer output = executor.execute("Compiler.queue"); + Iterator lines = output.asLines().iterator(); - String str = r.readLine(); - - while (str != null) { + while (lines.hasNext()) { + String str = lines.next(); if (str.startsWith("Contents of C")) { - match(r.readLine(), "----------------------------"); - str = r.readLine(); + match(lines.next(), "----------------------------"); + str = lines.next(); if (!str.equals("Empty")) { while (str.charAt(0) != '-') { validateMethodLine(str); - str = r.readLine(); + str = lines.next(); } } else { - str = r.readLine(); + str = lines.next(); } match(str,"----------------------------"); - str = r.readLine(); } else { - throw new Exception("Failed parsing dcmd queue, line: " + str); + throw new RuntimeException("Failed parsing dcmd queue, line: " + str); } } } - private static void validateMethodLine(String str) throws Exception { + private static void validateMethodLine(String str) { // Skip until package/class name begins. Trim to remove whitespace that // may differ. String name = str.substring(14).trim(); int sep = name.indexOf("::"); if (sep == -1) { - throw new Exception("Failed dcmd queue, didn't find separator :: in: " + name); + throw new RuntimeException("Failed dcmd queue, didn't find separator :: in: " + name); } try { Class.forName(name.substring(0, sep)); } catch (ClassNotFoundException e) { - throw new Exception("Failed dcmd queue, Class for name: " + str); + throw new RuntimeException("Failed dcmd queue, Class for name: " + str); } } - public static void match(String line, String str) throws Exception { + public static void match(String line, String str) { if (!line.equals(str)) { - throw new Exception("String equals: " + line + ", " + str); + throw new RuntimeException("String equals: " + line + ", " + str); } } + + @Test + public void jmx() { + run(new JMXExecutor()); + } } diff --git a/test/serviceability/dcmd/compiler/MethodIdentifierParser.java b/test/serviceability/dcmd/compiler/MethodIdentifierParser.java --- a/test/serviceability/dcmd/compiler/MethodIdentifierParser.java +++ b/test/serviceability/dcmd/compiler/MethodIdentifierParser.java @@ -51,11 +51,11 @@ // Add sanity check for extracted fields } - public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException, Exception { + public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException { try { return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray()); } catch (UnexpectedTokenException e) { - throw new Exception("Parse failed"); + throw new RuntimeException("Parse failed"); } } diff --git a/test/serviceability/dcmd/framework/HelpTest.java b/test/serviceability/dcmd/framework/HelpTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/framework/HelpTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.PidJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.MainClassJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.FileJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng HelpTest + */ +public class HelpTest { + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("help"); + + output.shouldContain("The following commands are available"); + output.shouldContain("help"); + output.shouldContain("VM.version"); + } + + @Test + public void pid() { + run(new PidJcmdExecutor()); + } + + @Test + public void mainClass() { + run(new MainClassJcmdExecutor()); + } + + @Test + public void file() { + run(new FileJcmdExecutor()); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } + +} diff --git a/test/serviceability/dcmd/framework/InvalidCommandTest.java b/test/serviceability/dcmd/framework/InvalidCommandTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/framework/InvalidCommandTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.PidJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.MainClassJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.FileJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng InvalidCommandTest + */ +public class InvalidCommandTest { + + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("asdf"); + output.shouldContain("Unknown diagnostic command"); + } + + @Test + public void pid() { + run(new PidJcmdExecutor()); + } + + @Test + public void mainClass() { + run(new MainClassJcmdExecutor()); + } + + @Test + public void file() { + run(new FileJcmdExecutor()); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/framework/VMVersionTest.java b/test/serviceability/dcmd/framework/VMVersionTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/framework/VMVersionTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.PidJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.MainClassJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.FileJcmdExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +import org.testng.annotations.Test; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng VMVersionTest + */ +public class VMVersionTest { + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("VM.version"); + output.shouldMatch(".*(?:HotSpot|OpenJDK).*VM.*"); + } + + @Test + public void pid() { + run(new PidJcmdExecutor()); + } + + @Test + public void mainClass() { + run(new MainClassJcmdExecutor()); + } + + @Test + public void file() { + run(new FileJcmdExecutor()); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/gc/ClassHistogramAllTest.java b/test/serviceability/dcmd/gc/ClassHistogramAllTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/gc/ClassHistogramAllTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @build ClassHistogramTest + * @run testng ClassHistogramAllTest + */ +public class ClassHistogramAllTest extends ClassHistogramTest { + public ClassHistogramAllTest() { + super(); + classHistogramArgs = "-all=true"; + } + + /* See ClassHistogramTest for test cases */ +} diff --git a/test/serviceability/dcmd/gc/ClassHistogramTest.java b/test/serviceability/dcmd/gc/ClassHistogramTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/gc/ClassHistogramTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.util.regex.Pattern; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng ClassHistogramTest + */ +public class ClassHistogramTest { + public static class TestClass {} + public static TestClass[] instances = new TestClass[1024]; + protected String classHistogramArgs = ""; + + static { + for (int i = 0; i < instances.length; ++i) { + instances[i] = new TestClass(); + } + } + + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("GC.class_histogram " + classHistogramArgs); + + /* + * example output: + * num #instances #bytes class name + * ---------------------------------------------- + * 1: 1647 1133752 [B + * 2: 6198 383168 [C + * 3: 1464 165744 java.lang.Class + * 4: 6151 147624 java.lang.String + * 5: 2304 73728 java.util.concurrent.ConcurrentHashMap$Node + * 6: 1199 64280 [Ljava.lang.Object; + * ... + */ + + /* Require at least one java.lang.Class */ + output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.Class\\s*$"); + + /* Require at least one java.lang.String */ + output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.String\\s*$"); + + /* Require at least one java.lang.Object */ + output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.Object\\s*$"); + + /* Require at exactly one TestClass[] */ + output.shouldMatch("^\\s+\\d+:\\s+1\\s+\\d+\\s+" + + Pattern.quote(TestClass[].class.getName()) + "\\s*$"); + + /* Require at exactly 1024 TestClass */ + output.shouldMatch("^\\s+\\d+:\\s+1024\\s+\\d+\\s+" + + Pattern.quote(TestClass.class.getName()) + "\\s*$"); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/gc/HeapDumpAllTest.java b/test/serviceability/dcmd/gc/HeapDumpAllTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/gc/HeapDumpAllTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @build HeapDumpTest + * @run testng HeapDumpAllTest + */ +public class HeapDumpAllTest extends HeapDumpTest { + public HeapDumpAllTest() { + super(); + heapDumpArgs = "-all=true"; + } + + /* See HeapDumpTest for test cases */ +} + diff --git a/test/serviceability/dcmd/gc/HeapDumpTest.java b/test/serviceability/dcmd/gc/HeapDumpTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/gc/HeapDumpTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.io.IOException; + +import com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.PidJcmdExecutor; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng HeapDumpTest + */ +public class HeapDumpTest { + protected String heapDumpArgs = ""; + + public void run(CommandExecutor executor) { + String fileName = "jcmd.gc.heap_dump." + System.currentTimeMillis() + ".hprof"; + String cmd = "GC.heap_dump " + heapDumpArgs + " " + fileName; + executor.execute(cmd); + + verifyHeapDump(fileName); + } + + private void verifyHeapDump(String fileName) { + String jhat = JDKToolFinder.getTestJDKTool("jhat"); + String[] cmd = { jhat, "-parseonly", "true", fileName }; + + ProcessBuilder pb = new ProcessBuilder(cmd); + pb.redirectErrorStream(true); + Process p = null; + OutputAnalyzer output; + + try { + p = pb.start(); + output = new OutputAnalyzer(p); + + /* + * Some hprof dumps of all objects contain constantPoolOop references that cannot be resolved, so we ignore + * failures about resolving constantPoolOop fields using a negative lookahead + */ + output.shouldNotMatch(".*WARNING(?!.*Failed to resolve object.*constantPoolOop.*).*"); + } catch (IOException e) { + throw new RuntimeException("Test error: Caught exception while reading stdout/err of jhat", e); + } finally { + if (p != null) { + p.destroy(); + } + } + + if (output.getExitValue() != 0) { + throw new RuntimeException("Test error: jhat exit code was nonzero"); + } + } + + /* GC.heap_dump is not available over JMX, running jcmd pid executor instead */ + @Test + public void pid() { + run(new PidJcmdExecutor()); + } +} + diff --git a/test/serviceability/dcmd/gc/RunFinalizationTest.java b/test/serviceability/dcmd/gc/RunFinalizationTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/gc/RunFinalizationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng RunFinalizationTest + */ +public class RunFinalizationTest { + static ReentrantLock lock = new ReentrantLock(); + static Condition cond = lock.newCondition(); + static volatile boolean wasFinalized = false; + static volatile boolean wasInitialized = false; + + class MyObject { + public MyObject() { + /* Make sure object allocation/deallocation is not optimized out */ + wasInitialized = true; + } + + protected void finalize() { + lock.lock(); + wasFinalized = true; + cond.signalAll(); + lock.unlock(); + } + } + + public static MyObject o; + + public void run(CommandExecutor executor) { + lock.lock(); + o = new MyObject(); + o = null; + System.gc(); + executor.execute("GC.run_finalization"); + + int waited = 0; + int waitTime = 15; + + try { + System.out.println("Waiting for signal from finalizer"); + + while (!cond.await(waitTime, TimeUnit.SECONDS)) { + waited += waitTime; + System.out.println(String.format("Waited %d seconds", waited)); + } + + System.out.println("Received signal"); + } catch (InterruptedException e) { + throw new RuntimeException("Test error: Interrupted while waiting for signal from finalizer", e); + } finally { + lock.unlock(); + } + + if (!wasFinalized) { + throw new RuntimeException("Test failure: Object was not finalized"); + } + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/gc/RunGCTest.java b/test/serviceability/dcmd/gc/RunGCTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/gc/RunGCTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng/othervm -XX:+PrintGCDetails -Xloggc:RunGC.gclog RunGCTest + */ +public class RunGCTest { + public void run(CommandExecutor executor) { + executor.execute("GC.run"); + + Path gcLogPath = Paths.get("RunGC.gclog").toAbsolutePath(); + String gcLog; + + try { + gcLog = new String(Files.readAllBytes(gcLogPath)); + } catch (IOException e) { + throw new RuntimeException("Test error: Could not read GC log file: " + gcLogPath, e); + } + + OutputAnalyzer output = new OutputAnalyzer(gcLog, ""); + output.shouldMatch(".*\\[Full GC \\(System(\\.gc\\(\\))?.*"); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java b/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @build PrintTest + * @run testng PrintConcurrentLocksTest + */ +public class PrintConcurrentLocksTest extends PrintTest { + public PrintConcurrentLocksTest() { + jucLocks = true; + } + + /* See PrintTest for test cases */ +} diff --git a/test/serviceability/dcmd/thread/PrintTest.java b/test/serviceability/dcmd/thread/PrintTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/thread/PrintTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import org.testng.annotations.Test; + +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.locks.ReentrantLock; +import java.util.regex.Pattern; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng PrintTest + */ +public class PrintTest { + protected boolean jucLocks = false; + + CyclicBarrier readyBarrier = new CyclicBarrier(3); + CyclicBarrier doneBarrier = new CyclicBarrier(3); + + private void waitForBarrier(CyclicBarrier b) { + try { + b.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException("Test error: Caught unexpected exception:", e); + } + } + + class MonitorThread extends Thread { + Object lock = new Object(); + + public void run() { + /* Hold lock on "lock" to show up in thread dump */ + synchronized (lock) { + /* Signal that we're ready for thread dump */ + waitForBarrier(readyBarrier); + + /* Released when the thread dump has been taken */ + waitForBarrier(doneBarrier); + } + } + } + + class LockThread extends Thread { + ReentrantLock lock = new ReentrantLock(); + + public void run() { + /* Hold lock "lock" to show up in thread dump */ + lock.lock(); + + /* Signal that we're ready for thread dump */ + waitForBarrier(readyBarrier); + + /* Released when the thread dump has been taken */ + waitForBarrier(doneBarrier); + + lock.unlock(); + } + } + + public void run(CommandExecutor executor) { + MonitorThread mThread = new MonitorThread(); + mThread.start(); + LockThread lThread = new LockThread(); + lThread.start(); + + /* Wait for threads to get ready */ + waitForBarrier(readyBarrier); + + /* Execute */ + OutputAnalyzer output = executor.execute("Thread.print" + (jucLocks ? " -l=true" : "")); + + /* Signal that we've got the thread dump */ + waitForBarrier(doneBarrier); + + /* + * Example output (trimmed) with arrows indicating the rows we are looking for: + * + * ... + * "Thread-2" #24 prio=5 os_prio=0 tid=0x00007f913411f800 nid=0x4fc9 waiting on condition [0x00007f91fbffe000] + * java.lang.Thread.State: WAITING (parking) + * at sun.misc.Unsafe.park(Native Method) + * - parking to wait for <0x000000071a0868a8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) + * at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) + * at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) + * at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234) + * at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) + * at Print.waitForBarrier(Print.java:26) + * at Print.access$000(Print.java:18) + * at Print$LockThread.run(Print.java:58) + * + * --> Locked ownable synchronizers: + * --> - <0x000000071a294930> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) + * + * "Thread-1" #23 prio=5 os_prio=0 tid=0x00007f913411e800 nid=0x4fc8 waiting on condition [0x00007f9200113000] + * java.lang.Thread.State: WAITING (parking) + * at sun.misc.Unsafe.park(Native Method) + * - parking to wait for <0x000000071a0868a8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) + * at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) + * at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) + * at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234) + * at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) + * at Print.waitForBarrier(Print.java:26) + * at Print.access$000(Print.java:18) + * at Print$MonitorThread.run(Print.java:42) + * --> - locked <0x000000071a294390> (a java.lang.Object) + * + * Locked ownable synchronizers: + * - None + * + * "MainThread" #22 prio=5 os_prio=0 tid=0x00007f923015b000 nid=0x4fc7 in Object.wait() [0x00007f9200840000] + * java.lang.Thread.State: WAITING (on object monitor) + * at java.lang.Object.wait(Native Method) + * - waiting on <0x000000071a70ad98> (a java.lang.UNIXProcess) + * at java.lang.Object.wait(Object.java:502) + * at java.lang.UNIXProcess.waitFor(UNIXProcess.java:397) + * - locked <0x000000071a70ad98> (a java.lang.UNIXProcess) + * at com.oracle.java.testlibrary.dcmd.JcmdExecutor.executeImpl(JcmdExecutor.java:32) + * at com.oracle.java.testlibrary.dcmd.CommandExecutor.execute(CommandExecutor.java:24) + * --> at Print.run(Print.java:74) + * at Print.file(Print.java:112) + * ... + + */ + output.shouldMatch(".*at " + Pattern.quote(PrintTest.class.getName()) + "\\.run.*"); + output.shouldMatch(".*- locked <0x\\p{XDigit}+> \\(a " + Pattern.quote(mThread.lock.getClass().getName()) + "\\).*"); + + String jucLockPattern1 = ".*Locked ownable synchronizers:.*"; + String jucLockPattern2 = ".*- <0x\\p{XDigit}+> \\(a " + Pattern.quote(lThread.lock.getClass().getName()) + ".*"; + + if (jucLocks) { + output.shouldMatch(jucLockPattern1); + output.shouldMatch(jucLockPattern2); + } else { + output.shouldNotMatch(jucLockPattern1); + output.shouldNotMatch(jucLockPattern2); + } + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java b/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng ClassLoaderStatsTest + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ClassLoaderStatsTest { + + // ClassLoader Parent CLD* Classes ChunkSz BlockSz Type + // 0x00000007c0215928 0x0000000000000000 0x0000000000000000 0 0 0 org.eclipse.osgi.baseadaptor.BaseAdaptor$1 + // 0x00000007c0009868 0x0000000000000000 0x00007fc52aebcc80 1 6144 3768 sun.reflect.DelegatingClassLoader + // 0x00000007c0009868 0x0000000000000000 0x00007fc52b8916d0 1 6144 3688 sun.reflect.DelegatingClassLoader + // 0x00000007c0009868 0x00000007c0038ba8 0x00007fc52afb8760 1 6144 3688 sun.reflect.DelegatingClassLoader + // 0x00000007c0009868 0x0000000000000000 0x00007fc52afbb1a0 1 6144 3688 sun.reflect.DelegatingClassLoader + // 0x0000000000000000 0x0000000000000000 0x00007fc523416070 5019 30060544 29956216 + // 455 1210368 672848 + unsafe anonymous classes + // 0x00000007c016b5c8 0x00000007c0038ba8 0x00007fc52a995000 5 8192 5864 org.netbeans.StandardModule$OneModuleClassLoader + // 0x00000007c0009868 0x00000007c016b5c8 0x00007fc52ac13640 1 6144 3896 sun.reflect.DelegatingClassLoader + // ... + + static Pattern clLine = Pattern.compile("0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(.*)"); + static Pattern anonLine = Pattern.compile("\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*.*"); + + public static DummyClassLoader dummyloader; + + public void run(CommandExecutor executor) throws ClassNotFoundException { + + // create a classloader and load our special class + dummyloader = new DummyClassLoader(); + Class c = Class.forName("TestClass", true, dummyloader); + if (c.getClassLoader() != dummyloader) { + throw new RuntimeException("TestClass defined by wrong classloader: " + c.getClassLoader()); + } + + OutputAnalyzer output = executor.execute("VM.classloader_stats"); + Iterator lines = output.asLines().iterator(); + while (lines.hasNext()) { + String line = lines.next(); + Matcher m = clLine.matcher(line); + if (m.matches()) { + // verify that DummyClassLoader has loaded 1 class and 1 anonymous class + if (m.group(4).equals("ClassLoaderStatsTest$DummyClassLoader")) { + System.out.println("line: " + line); + if (!m.group(1).equals("1")) { + throw new RuntimeException("Should have loaded 1 class: " + line); + } + checkPositiveInt(m.group(2)); + checkPositiveInt(m.group(3)); + + String next = lines.next(); + System.out.println("next: " + next); + Matcher m1 = anonLine.matcher(next); + m1.matches(); + if (!m1.group(1).equals("1")) { + throw new RuntimeException("Should have loaded 1 anonymous class, but found : " + m1.group(1)); + } + checkPositiveInt(m1.group(2)); + checkPositiveInt(m1.group(3)); + } + } + } + } + + private static void checkPositiveInt(String s) { + if (Integer.parseInt(s) <= 0) { + throw new RuntimeException("Value should have been > 0: " + s); + } + } + + public static class DummyClassLoader extends ClassLoader { + + public static final String CLASS_NAME = "TestClass"; + + static ByteBuffer readClassFile(String name) + { + File f = new File(System.getProperty("test.classes", "."), + name); + try (FileInputStream fin = new FileInputStream(f); + FileChannel fc = fin.getChannel()) + { + return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); + } catch (IOException e) { + throw new RuntimeException("Can't open file: " + name, e); + } + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + Class c; + if (!"TestClass".equals(name)) { + c = super.loadClass(name, resolve); + } else { + // should not delegate to the system class loader + c = findClass(name); + if (resolve) { + resolveClass(c); + } + } + return c; + } + + protected Class findClass(String name) + throws ClassNotFoundException + { + if (!"TestClass".equals(name)) { + throw new ClassNotFoundException("Unexpected class: " + name); + } + return defineClass(name, readClassFile(name + ".class"), null); + } + } /* DummyClassLoader */ + + @Test + public void jmx() throws ClassNotFoundException { + run(new JMXExecutor()); + } +} + +class TestClass { + static { + // force creation of anonymous class (for the lambdaform) + Runnable r = () -> System.out.println("Hello"); + r.run(); + } +} diff --git a/test/serviceability/dcmd/vm/CommandLineTest.java b/test/serviceability/dcmd/vm/CommandLineTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/vm/CommandLineTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import org.testng.annotations.Test; + +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis CommandLineTest + */ +public class CommandLineTest { + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("VM.command_line"); + output.shouldContain("-XX:+IgnoreUnrecognizedVMOptions"); + output.shouldContain("-XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis"); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/vm/DynLibsTest.java b/test/serviceability/dcmd/vm/DynLibsTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/vm/DynLibsTest.java @@ -0,0 +1,70 @@ +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test of VM.dynlib diagnostic command via MBean + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng DynLibsTest + */ + +public class DynLibsTest { + + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("VM.dynlibs"); + + String osDependentBaseString = null; + if (Platform.isAix()) { + osDependentBaseString = "lib%s.so"; + } else if (Platform.isLinux()) { + osDependentBaseString = "lib%s.so"; + } else if (Platform.isOSX()) { + osDependentBaseString = "lib%s.dylib"; + } else if (Platform.isSolaris()) { + osDependentBaseString = "lib%s.so"; + } else if (Platform.isWindows()) { + osDependentBaseString = "%s.dll"; + } + + if (osDependentBaseString == null) { + throw new RuntimeException("Unsupported OS"); + } + + output.shouldContain(String.format(osDependentBaseString, "jvm")); + output.shouldContain(String.format(osDependentBaseString, "java")); + output.shouldContain(String.format(osDependentBaseString, "management")); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/vm/FlagsTest.java b/test/serviceability/dcmd/vm/FlagsTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/vm/FlagsTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng/othervm -Xmx129m -XX:+PrintGC -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis_Right -XX:-TieredCompilation FlagsTest + */ +public class FlagsTest { + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("VM.flags"); + + /* The following are interpreted by the JVM as actual "flags" */ + output.shouldContain("-XX:+PrintGC"); + output.shouldContain("-XX:+UnlockDiagnosticVMOptions"); + output.shouldContain("-XX:+IgnoreUnrecognizedVMOptions"); + output.shouldContain("-XX:-TieredCompilation"); + + /* The following are not */ + output.shouldNotContain("-Xmx129m"); + output.shouldNotContain("-XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis_Right"); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/vm/SystemPropertiesTest.java b/test/serviceability/dcmd/vm/SystemPropertiesTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/vm/SystemPropertiesTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng SystemPropertiesTest + */ +public class SystemPropertiesTest { + private final static String PROPERTY_NAME = "SystemPropertiesTestPropertyName"; + private final static String PROPERTY_VALUE = "SystemPropertiesTestPropertyValue"; + + public void run(CommandExecutor executor) { + System.setProperty(PROPERTY_NAME, PROPERTY_VALUE); + + OutputAnalyzer output = executor.execute("VM.system_properties"); + output.shouldContain(PROPERTY_NAME + "=" + PROPERTY_VALUE); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/serviceability/dcmd/vm/UptimeTest.java b/test/serviceability/dcmd/vm/UptimeTest.java new file mode 100644 --- /dev/null +++ b/test/serviceability/dcmd/vm/UptimeTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.dcmd.CommandExecutor; +import com.oracle.java.testlibrary.dcmd.JMXExecutor; +import org.testng.annotations.Test; + +import java.text.NumberFormat; +import java.text.ParseException; + +/* + * @test + * @library /testlibrary + * @build com.oracle.java.testlibrary.* + * @build com.oracle.java.testlibrary.dcmd.* + * @run testng UptimeTest + */ +public class UptimeTest { + public void run(CommandExecutor executor) { + double someUptime = 1.0; + try { + synchronized (this) { + wait((int) someUptime * 1000); + } + } catch (InterruptedException e) { + throw new RuntimeException("Test error: Exception caught when sleeping:", e); + } + + OutputAnalyzer output = executor.execute("VM.uptime"); + + output.stderrShouldBeEmpty(); + + /* + * Output should be: + * [pid]: + * xx.yyy s + * + * If there is only one line in output there is no "[pid]:" printout; + * skip first line, split on whitespace and grab first half + */ + int index = output.asLines().size() == 1 ? 0 : 1; + String uptimeString = output.asLines().get(index).split("\\s+")[0]; + + try { + double uptime = NumberFormat.getNumberInstance().parse(uptimeString).doubleValue(); + if (uptime < someUptime) { + throw new RuntimeException(String.format( + "Test failure: Uptime was less than intended sleep time: %.3f s < %.3f s", + uptime, someUptime)); + } + } catch (ParseException e) { + throw new RuntimeException("Test failure: Could not parse uptime string: " + + uptimeString, e); + } + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutor.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutor.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutor.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +import com.oracle.java.testlibrary.OutputAnalyzer; + +/** + * Abstract base class for Diagnostic Command executors + */ +public abstract class CommandExecutor { + + /** + * Execute a diagnostic command + * + * @param cmd The diagnostic command to execute + * @return an {@link jdk.testlibrary.OutputAnalyzer} encapsulating the output of the command + * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the + * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in + * stderr, regardless of the specific executor used. + */ + public final OutputAnalyzer execute(String cmd) throws CommandExecutorException { + System.out.printf("Running DCMD '%s' through '%s'%n", cmd, this.getClass().getSimpleName()); + OutputAnalyzer oa = executeImpl(cmd); + + System.out.println("---------------- stdout ----------------"); + System.out.println(oa.getStdout()); + System.out.println("---------------- stderr ----------------"); + System.out.println(oa.getStderr()); + System.out.println("----------------------------------------"); + System.out.println(); + + return oa; + } + + protected abstract OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException; +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutorException.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutorException.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutorException.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +/** + * CommandExecutorException encapsulates exceptions thrown (on the "calling side") from the execution of Diagnostic + * Commands + */ +public class CommandExecutorException extends RuntimeException { + private static final long serialVersionUID = -7039597746579144280L; + + public CommandExecutorException(String message, Throwable e) { + super(message, e); + } +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/FileJcmdExecutor.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/FileJcmdExecutor.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/FileJcmdExecutor.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; + +/** + * Executes Diagnostic Commands on the target VM (specified by pid) using the jcmd tool and its ability to read + * Diagnostic Commands from a file. + */ +public class FileJcmdExecutor extends PidJcmdExecutor { + + /** + * Instantiates a new FileJcmdExecutor targeting the current VM + */ + public FileJcmdExecutor() { + super(); + } + + /** + * Instantiates a new FileJcmdExecutor targeting the VM indicated by the given pid + * + * @param target Pid of the target VM + */ + public FileJcmdExecutor(String target) { + super(target); + } + + protected List createCommandLine(String cmd) throws CommandExecutorException { + File cmdFile = createTempFile(); + writeCommandToTemporaryFile(cmd, cmdFile); + + return Arrays.asList(jcmdBinary, Integer.toString(pid), + "-f", cmdFile.getAbsolutePath()); + } + + private void writeCommandToTemporaryFile(String cmd, File cmdFile) { + try (PrintWriter pw = new PrintWriter(cmdFile)) { + pw.println(cmd); + } catch (IOException e) { + String message = "Could not write to file: " + cmdFile.getAbsolutePath(); + throw new CommandExecutorException(message, e); + } + } + + private File createTempFile() { + try { + File cmdFile = File.createTempFile("input", "jcmd"); + cmdFile.deleteOnExit(); + return cmdFile; + } catch (IOException e) { + throw new CommandExecutorException("Could not create temporary file", e); + } + } + +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/JMXExecutor.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/JMXExecutor.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/JMXExecutor.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +import com.oracle.java.testlibrary.OutputAnalyzer; + +import javax.management.*; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import java.lang.management.ManagementFactory; + +import java.util.HashMap; + +/** + * Executes Diagnostic Commands on the target VM (specified by a host/port combination or a full JMX Service URL) using + * the JMX interface. If the target is not the current VM, the JMX Remote interface must be enabled beforehand. + */ +public class JMXExecutor extends CommandExecutor { + + private final MBeanServerConnection mbs; + + /** + * Instantiates a new JMXExecutor targeting the current VM + */ + public JMXExecutor() { + super(); + mbs = ManagementFactory.getPlatformMBeanServer(); + } + + /** + * Instantiates a new JMXExecutor targeting the VM indicated by the given host/port combination or a full JMX + * Service URL + * + * @param target a host/port combination on the format "host:port" or a full JMX Service URL of the target VM + */ + public JMXExecutor(String target) { + String urlStr; + + if (target.matches("^\\w[\\w\\-]*(\\.[\\w\\-]+)*:\\d+$")) { + /* Matches "hostname:port" */ + urlStr = String.format("service:jmx:rmi:///jndi/rmi://%s/jmxrmi", target); + } else if (target.startsWith("service:")) { + urlStr = target; + } else { + throw new IllegalArgumentException("Could not recognize target string: " + target); + } + + try { + JMXServiceURL url = new JMXServiceURL(urlStr); + JMXConnector c = JMXConnectorFactory.connect(url, new HashMap<>()); + mbs = c.getMBeanServerConnection(); + } catch (IOException e) { + throw new CommandExecutorException("Could not initiate connection to target: " + target, e); + } + } + + protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException { + String stdout = ""; + String stderr = ""; + + String[] cmdParts = cmd.split(" ", 2); + String operation = commandToMethodName(cmdParts[0]); + Object[] dcmdArgs = produceArguments(cmdParts); + String[] signature = {String[].class.getName()}; + + ObjectName beanName = getMBeanName(); + + try { + stdout = (String) mbs.invoke(beanName, operation, dcmdArgs, signature); + } + + /* Failures on the "local" side, the one invoking the command. */ + catch (ReflectionException e) { + Throwable cause = e.getCause(); + if (cause instanceof NoSuchMethodException) { + /* We want JMXExecutor to match the behavior of the other CommandExecutors */ + String message = "Unknown diagnostic command: " + operation; + stderr = exceptionTraceAsString(new IllegalArgumentException(message, e)); + } else { + rethrowExecutorException(operation, dcmdArgs, e); + } + } + + /* Failures on the "local" side, the one invoking the command. */ + catch (InstanceNotFoundException | IOException e) { + rethrowExecutorException(operation, dcmdArgs, e); + } + + /* Failures on the remote side, the one executing the invoked command. */ + catch (MBeanException e) { + stdout = exceptionTraceAsString(e); + } + + return new OutputAnalyzer(stdout, stderr); + } + + private void rethrowExecutorException(String operation, Object[] dcmdArgs, + Exception e) throws CommandExecutorException { + String message = String.format("Could not invoke: %s %s", operation, + String.join(" ", (String[]) dcmdArgs[0])); + throw new CommandExecutorException(message, e); + } + + private ObjectName getMBeanName() throws CommandExecutorException { + String MBeanName = "com.sun.management:type=DiagnosticCommand"; + + try { + return new ObjectName(MBeanName); + } catch (MalformedObjectNameException e) { + String message = "MBean not found: " + MBeanName; + throw new CommandExecutorException(message, e); + } + } + + private Object[] produceArguments(String[] cmdParts) { + Object[] dcmdArgs = {new String[0]}; /* Default: No arguments */ + + if (cmdParts.length == 2) { + dcmdArgs[0] = cmdParts[1].split(" "); + } + return dcmdArgs; + } + + /** + * Convert from diagnostic command to MBean method name + * + * Examples: + * help --> help + * VM.version --> vmVersion + * VM.command_line --> vmCommandLine + */ + private static String commandToMethodName(String cmd) { + String operation = ""; + boolean up = false; /* First letter is to be lower case */ + + /* + * If a '.' or '_' is encountered it is not copied, + * instead the next character will be converted to upper case + */ + for (char c : cmd.toCharArray()) { + if (('.' == c) || ('_' == c)) { + up = true; + } else if (up) { + operation = operation.concat(Character.toString(c).toUpperCase()); + up = false; + } else { + operation = operation.concat(Character.toString(c).toLowerCase()); + } + } + + return operation; + } + + private static String exceptionTraceAsString(Throwable cause) { + StringWriter sw = new StringWriter(); + cause.printStackTrace(new PrintWriter(sw)); + return sw.toString(); + } + +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/JcmdExecutor.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/JcmdExecutor.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/JcmdExecutor.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +import com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.util.List; + +/** + * Base class for Diagnostic Command Executors using the jcmd tool + */ +public abstract class JcmdExecutor extends CommandExecutor { + protected String jcmdBinary; + + protected abstract List createCommandLine(String cmd) throws CommandExecutorException; + + protected JcmdExecutor() { + jcmdBinary = JDKToolFinder.getJDKTool("jcmd"); + } + + protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException { + List commandLine = createCommandLine(cmd); + + try { + System.out.printf("Executing command '%s'%n", commandLine); + OutputAnalyzer output = ProcessTools.executeProcess(new ProcessBuilder(commandLine)); + System.out.printf("Command returned with exit code %d%n", output.getExitValue()); + + return output; + } catch (Exception e) { + String message = String.format("Caught exception while executing '%s'", commandLine); + throw new CommandExecutorException(message, e); + } + } +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/MainClassJcmdExecutor.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/MainClassJcmdExecutor.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/MainClassJcmdExecutor.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +import java.util.Arrays; +import java.util.List; + +/** + * Executes Diagnostic Commands on the target VM (specified by main class) using the jcmd tool + */ +public class MainClassJcmdExecutor extends JcmdExecutor { + private final String mainClass; + + /** + * Instantiates a new MainClassJcmdExecutor targeting the current VM + */ + public MainClassJcmdExecutor() { + super(); + mainClass = System.getProperty("sun.java.command").split(" ")[0]; + } + + /** + * Instantiates a new MainClassJcmdExecutor targeting the VM indicated by the given main class + * + * @param target Main class of the target VM + */ + public MainClassJcmdExecutor(String target) { + super(); + mainClass = target; + } + + protected List createCommandLine(String cmd) throws CommandExecutorException { + return Arrays.asList(jcmdBinary, mainClass, cmd); + } + +} diff --git a/test/testlibrary/com/oracle/java/testlibrary/dcmd/PidJcmdExecutor.java b/test/testlibrary/com/oracle/java/testlibrary/dcmd/PidJcmdExecutor.java new file mode 100644 --- /dev/null +++ b/test/testlibrary/com/oracle/java/testlibrary/dcmd/PidJcmdExecutor.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.dcmd; + +import com.oracle.java.testlibrary.ProcessTools; + +import java.util.Arrays; +import java.util.List; + +/** + * Executes Diagnostic Commands on the target VM (specified by pid) using the jcmd tool + */ +public class PidJcmdExecutor extends JcmdExecutor { + protected final int pid; + + /** + * Instantiates a new PidJcmdExecutor targeting the current VM + */ + public PidJcmdExecutor() { + super(); + try { + pid = ProcessTools.getProcessId(); + } catch (Exception e) { + throw new CommandExecutorException("Could not determine own pid", e); + } + } + + /** + * Instantiates a new PidJcmdExecutor targeting the VM indicated by the given pid + * + * @param target Pid of the target VM + */ + public PidJcmdExecutor(String target) { + super(); + pid = Integer.valueOf(target); + } + + protected List createCommandLine(String cmd) throws CommandExecutorException { + return Arrays.asList(jcmdBinary, Integer.toString(pid), cmd); + } + +}