aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authoramurillo <none@none>2014-02-28 08:43:42 -0800
committeramurillo <none@none>2014-02-28 08:43:42 -0800
commit6d488647762b5c67144b96ee6ab5c8c51e1db523 (patch)
tree9564b8c15d601270cd6c9c24fec7b9ae3eac33fa /test
parentc889b5e8a0819e9b8f1c28aa1dbaae0ed6d8524a (diff)
parent50ae7d69ceb27273d8de36bc595837941151b188 (diff)
Diffstat (limited to 'test')
-rw-r--r--test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java82
-rw-r--r--test/serviceability/jvmti/UnresolvedClassAgent.java69
-rw-r--r--test/serviceability/jvmti/UnresolvedClassAgent.mf3
-rw-r--r--test/serviceability/sa/jmap-hashcode/Test8028623.java74
-rw-r--r--test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java81
-rw-r--r--test/testlibrary/com/oracle/java/testlibrary/Utils.java263
6 files changed, 570 insertions, 2 deletions
diff --git a/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java b/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
new file mode 100644
index 000000000..4f929c49a
--- /dev/null
+++ b/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
@@ -0,0 +1,82 @@
+/*
+ * 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
+ * @summary Redefine a class with an UnresolvedClass reference in the constant pool.
+ * @bug 8035150
+ * @library /testlibrary
+ * @build UnresolvedClassAgent com.oracle.java.testlibrary.ProcessTools com.oracle.java.testlibrary.OutputAnalyzer
+ * @run main TestRedefineWithUnresolvedClass
+ */
+
+import java.io.File;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestRedefineWithUnresolvedClass {
+
+ final static String slash = File.separator;
+ final static String testClasses = System.getProperty("test.classes") + slash;
+
+ public static void main(String... args) throws Throwable {
+ // delete this class to cause a NoClassDefFoundError
+ File unresolved = new File(testClasses, "MyUnresolvedClass.class");
+ if (unresolved.exists() && !unresolved.delete()) {
+ throw new Exception("Could not delete: " + unresolved);
+ }
+
+ // build the javaagent
+ buildJar("UnresolvedClassAgent");
+
+ // launch a VM with the javaagent
+ launchTest();
+ }
+
+ private static void buildJar(String jarName) throws Throwable {
+ String testSrc = System.getProperty("test.src", "?") + slash;
+
+ String jarPath = String.format("%s%s.jar", testClasses, jarName);
+ String manifestPath = String.format("%s%s.mf", testSrc, jarName);
+ String className = String.format("%s.class", jarName);
+
+ String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
+
+ System.out.println("Running jar " + Arrays.toString(args));
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(args)) {
+ throw new Exception("jar failed: args=" + Arrays.toString(args));
+ }
+ }
+
+ private static void launchTest() throws Throwable {
+ String[] args = {
+ "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
+ "-Dtest.classes=" + testClasses,
+ "UnresolvedClassAgent" };
+ OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+ }
+}
diff --git a/test/serviceability/jvmti/UnresolvedClassAgent.java b/test/serviceability/jvmti/UnresolvedClassAgent.java
new file mode 100644
index 000000000..efe7b25a1
--- /dev/null
+++ b/test/serviceability/jvmti/UnresolvedClassAgent.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+
+/*
+ * This class is present during compilation, but will be deleted before execution.
+ */
+class MyUnresolvedClass {
+ static void bar() {
+ }
+}
+
+class MyRedefinedClass {
+ static void foo() {
+ MyUnresolvedClass.bar();
+ }
+}
+
+public class UnresolvedClassAgent {
+ public static void main(String... args) {
+ }
+
+ public static void premain(String args, Instrumentation inst) throws Exception {
+ try {
+ MyRedefinedClass.foo();
+ } catch(NoClassDefFoundError err) {
+ System.out.println("NoClassDefFoundError (expected)");
+ }
+
+ File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
+ byte[] buf = new byte[(int)f.length()];
+ try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
+ dis.readFully(buf);
+ }
+ ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
+ inst.redefineClasses(new ClassDefinition[] {cd});
+
+ try {
+ MyRedefinedClass.foo();
+ } catch(NoClassDefFoundError err) {
+ System.out.println("NoClassDefFoundError (expected again)");
+ }
+ }
+}
diff --git a/test/serviceability/jvmti/UnresolvedClassAgent.mf b/test/serviceability/jvmti/UnresolvedClassAgent.mf
new file mode 100644
index 000000000..5570570cd
--- /dev/null
+++ b/test/serviceability/jvmti/UnresolvedClassAgent.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Premain-Class: UnresolvedClassAgent
+Can-Redefine-Classes: true
diff --git a/test/serviceability/sa/jmap-hashcode/Test8028623.java b/test/serviceability/sa/jmap-hashcode/Test8028623.java
new file mode 100644
index 000000000..bd743ab1c
--- /dev/null
+++ b/test/serviceability/sa/jmap-hashcode/Test8028623.java
@@ -0,0 +1,74 @@
+/*
+ * 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
+ * @bug 8028623
+ * @summary Test hashing of extended characters in Serviceability Agent.
+ * @library /testlibrary
+ * @compile -encoding utf8 Test8028623.java
+ * @run main Test8028623
+ */
+
+import com.oracle.java.testlibrary.JDKToolLauncher;
+import com.oracle.java.testlibrary.OutputBuffer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+import java.io.File;
+
+public class Test8028623 {
+
+ public static int à = 1;
+ public static String dumpFile = "heap.out";
+
+ public static void main (String[] args) {
+
+ System.out.println(Ã);
+
+ try {
+ int pid = ProcessTools.getProcessId();
+ JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ .addToolArg("-F")
+ .addToolArg("-dump:live,format=b,file=" + dumpFile)
+ .addToolArg(Integer.toString(pid));
+ ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ OutputBuffer output = ProcessTools.getOutput(pb);
+ Process p = pb.start();
+ int e = p.waitFor();
+ System.out.println("stdout:");
+ System.out.println(output.getStdout());
+ System.out.println("stderr:");
+ System.out.println(output.getStderr());
+
+ if (e != 0) {
+ throw new RuntimeException("jmap returns: " + e);
+ }
+ if (! new File(dumpFile).exists()) {
+ throw new RuntimeException("dump file NOT created: '" + dumpFile + "'");
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new RuntimeException("Test failed with: " + t);
+ }
+ }
+}
diff --git a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java
index 56277f046..64b1b9ea9 100644
--- a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java
+++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java
@@ -151,11 +151,88 @@ public final class ProcessTools {
// Reporting
StringBuilder cmdLine = new StringBuilder();
- for (String cmd : args)
- cmdLine.append(cmd).append(' ');
+ for (String cmd : args) {
+ cmdLine.append(cmd).append(' ');
+ }
System.out.println("Command line: [" + cmdLine.toString() + "]");
return new ProcessBuilder(args.toArray(new String[args.size()]));
}
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvm(String... cmds) throws Throwable {
+ ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds));
+ 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.
+ * @param cmds The command line to execute.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeProcess(String... cmds) throws Throwable {
+ return executeProcess(new ProcessBuilder(cmds));
+ }
+
+ /**
+ * Used to log command line, stdout, stderr and exit code from an executed process.
+ * @param pb The executed process.
+ * @param output The output from the process.
+ */
+ public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) {
+ String stderr = output == null ? "null" : output.getStderr();
+ String stdout = output == null ? "null" : output.getStdout();
+ String exitValue = output == null ? "null": Integer.toString(output.getExitValue());
+ StringBuilder logMsg = new StringBuilder();
+ final String nl = System.getProperty("line.separator");
+ logMsg.append("--- ProcessLog ---" + nl);
+ logMsg.append("cmd: " + getCommandLine(pb) + nl);
+ logMsg.append("exitvalue: " + exitValue + nl);
+ logMsg.append("stderr: " + stderr + nl);
+ logMsg.append("stdout: " + stdout + nl);
+ return logMsg.toString();
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ if (pb == null) {
+ return "null";
+ }
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString().trim();
+ }
+
}
diff --git a/test/testlibrary/com/oracle/java/testlibrary/Utils.java b/test/testlibrary/com/oracle/java/testlibrary/Utils.java
new file mode 100644
index 000000000..a0031e706
--- /dev/null
+++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+import static com.oracle.java.testlibrary.Asserts.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Common library for various test helper functions.
+ */
+public final class Utils {
+
+ /**
+ * Returns the sequence used by operating system to separate lines.
+ */
+ public static final String NEW_LINE = System.getProperty("line.separator");
+
+ /**
+ * Returns the value of 'test.vm.opts'system property.
+ */
+ public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim();
+
+ /**
+ * Returns the value of 'test.java.opts'system property.
+ */
+ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
+
+ /**
+ * Returns the value of 'test.timeout.factor' system property
+ * converted to {@code double}.
+ */
+ public static final double TIMEOUT_FACTOR;
+ static {
+ String toFactor = System.getProperty("test.timeout.factor", "1.0");
+ TIMEOUT_FACTOR = Double.parseDouble(toFactor);
+ }
+
+ private Utils() {
+ // Private constructor to prevent class instantiation
+ }
+
+ /**
+ * Returns the list of VM options.
+ *
+ * @return List of VM options
+ */
+ public static List<String> getVmOptions() {
+ return Arrays.asList(safeSplitString(VM_OPTIONS));
+ }
+
+ /**
+ * Returns the list of VM options with -J prefix.
+ *
+ * @return The list of VM options with -J prefix
+ */
+ public static List<String> getForwardVmOptions() {
+ String[] opts = safeSplitString(VM_OPTIONS);
+ for (int i = 0; i < opts.length; i++) {
+ opts[i] = "-J" + opts[i];
+ }
+ return Arrays.asList(opts);
+ }
+
+ /**
+ * Returns the default JTReg arguments for a jvm running a test.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
+ * @return An array of options, or an empty array if no opptions.
+ */
+ public static String[] getTestJavaOpts() {
+ List<String> opts = new ArrayList<String>();
+ Collections.addAll(opts, safeSplitString(VM_OPTIONS));
+ Collections.addAll(opts, safeSplitString(JAVA_OPTIONS));
+ return opts.toArray(new String[0]);
+ }
+
+ /**
+ * Combines given arguments with default JTReg arguments for a jvm running a test.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts
+ * @return The combination of JTReg test java options and user args.
+ */
+ public static String[] addTestJavaOpts(String... userArgs) {
+ List<String> opts = new ArrayList<String>();
+ Collections.addAll(opts, getTestJavaOpts());
+ Collections.addAll(opts, userArgs);
+ return opts.toArray(new String[0]);
+ }
+
+ /**
+ * Splits a string by white space.
+ * Works like String.split(), but returns an empty array
+ * if the string is null or empty.
+ */
+ private static String[] safeSplitString(String s) {
+ if (s == null || s.trim().isEmpty()) {
+ return new String[] {};
+ }
+ return s.trim().split("\\s+");
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString();
+ }
+
+ /**
+ * Returns the free port on the local host.
+ * The function will spin until a valid port number is found.
+ *
+ * @return The port number
+ * @throws InterruptedException if any thread has interrupted the current thread
+ * @throws IOException if an I/O error occurs when opening the socket
+ */
+ public static int getFreePort() throws InterruptedException, IOException {
+ int port = -1;
+
+ while (port <= 0) {
+ Thread.sleep(100);
+
+ ServerSocket serverSocket = null;
+ try {
+ serverSocket = new ServerSocket(0);
+ port = serverSocket.getLocalPort();
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+ return port;
+ }
+
+ /**
+ * Returns the name of the local host.
+ *
+ * @return The host name
+ * @throws UnknownHostException if IP address of a host could not be determined
+ */
+ public static String getHostname() throws UnknownHostException {
+ InetAddress inetAddress = InetAddress.getLocalHost();
+ String hostName = inetAddress.getHostName();
+
+ assertTrue((hostName != null && !hostName.isEmpty()),
+ "Cannot get hostname");
+
+ return hostName;
+ }
+
+ /**
+ * Uses "jcmd -l" to search for a jvm pid. This function will wait
+ * forever (until jtreg timeout) for the pid to be found.
+ * @param key Regular expression to search for
+ * @return The found pid.
+ */
+ public static int waitForJvmPid(String key) throws Throwable {
+ final long iterationSleepMillis = 250;
+ System.out.println("waitForJvmPid: Waiting for key '" + key + "'");
+ System.out.flush();
+ while (true) {
+ int pid = tryFindJvmPid(key);
+ if (pid >= 0) {
+ return pid;
+ }
+ Thread.sleep(iterationSleepMillis);
+ }
+ }
+
+ /**
+ * Searches for a jvm pid in the output from "jcmd -l".
+ *
+ * Example output from jcmd is:
+ * 12498 sun.tools.jcmd.JCmd -l
+ * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
+ *
+ * @param key A regular expression to search for.
+ * @return The found pid, or -1 if Enot found.
+ * @throws Exception If multiple matching jvms are found.
+ */
+ public static int tryFindJvmPid(String key) throws Throwable {
+ OutputAnalyzer output = null;
+ try {
+ JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd");
+ jcmdLauncher.addToolArg("-l");
+ output = ProcessTools.executeProcess(jcmdLauncher.getCommand());
+ output.shouldHaveExitValue(0);
+
+ // Search for a line starting with numbers (pid), follwed by the key.
+ Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n");
+ Matcher matcher = pattern.matcher(output.getStdout());
+
+ int pid = -1;
+ if (matcher.find()) {
+ pid = Integer.parseInt(matcher.group(1));
+ System.out.println("findJvmPid.pid: " + pid);
+ if (matcher.find()) {
+ throw new Exception("Found multiple JVM pids for key: " + key);
+ }
+ }
+ return pid;
+ } catch (Throwable t) {
+ System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t));
+ throw t;
+ }
+ }
+
+ /**
+ * Returns file content as a list of strings
+ *
+ * @param file File to operate on
+ * @return List of strings
+ * @throws IOException
+ */
+ public static List<String> fileAsList(File file) throws IOException {
+ assertTrue(file.exists() && file.isFile(),
+ file.getAbsolutePath() + " does not exist or not a file");
+ List<String> output = new ArrayList<>();
+ try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) {
+ while (reader.ready()) {
+ output.add(reader.readLine().replace(NEW_LINE, ""));
+ }
+ }
+ return output;
+ }
+
+}