8048193: [tests] Replace JPS and stdout based PID retrieval by Process.getPid()

Reviewed-by: sla
This commit is contained in:
Jaroslav Bachorik 2014-07-01 15:00:33 +02:00
parent 7b43631edc
commit e614cf24ef
15 changed files with 172 additions and 301 deletions

View File

@ -23,41 +23,21 @@
/*
* A simple "Application" used by the Attach API unit tests. This application is
* launched by the test. It binds to a random port and shuts down when somebody
* connects to that port.
* Used port and pid are written both to stdout and to a specified file.
* launched by the test.
*/
import java.net.Socket;
import java.net.ServerSocket;
import java.io.PrintWriter;
import jdk.testlibrary.ProcessTools;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Application {
public static final String READY_MSG="ready";
public static final String SHUTDOWN_MSG="shutdown";
public static void main(String args[]) throws Exception {
// bind to a random port
if (args.length < 1) {
System.err.println("First argument should be path to output file.");
}
String outFileName = args[0];
ServerSocket ss = new ServerSocket(0);
int port = ss.getLocalPort();
int pid = ProcessTools.getProcessId();
System.out.println("shutdownPort=" + port);
System.out.println("pid=" + pid);
System.out.println(READY_MSG);
System.out.flush();
try (PrintWriter writer = new PrintWriter(outFileName)) {
writer.println("shutdownPort=" + port);
writer.println("pid=" + pid);
writer.println("done");
writer.flush();
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
while (!br.readLine().equals(SHUTDOWN_MSG));
}
// wait for test harness to connect
Socket s = ss.accept();
s.close();
ss.close();
}
}

View File

@ -38,7 +38,7 @@ import jdk.testlibrary.ProcessThread;
* @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757
* @summary Basic unit tests for the VM attach mechanism.
* @library /lib/testlibrary
* @run build jdk.testlibrary.* Agent BadAgent RedefineAgent Application Shutdown RedefineDummy RunnerUtil
* @run build jdk.testlibrary.* Agent BadAgent RedefineAgent Application RedefineDummy RunnerUtil
* @run main BasicTests
*
* This test will perform a number of basic attach tests.
@ -55,21 +55,18 @@ public class BasicTests {
* 5. Shut down the Application.
*/
public static void main(String args[]) throws Throwable {
final String pidFile = "TestsBasic.Application.pid";
ProcessThread processThread = null;
RunnerUtil.ProcessInfo info = null;
try {
buildJars();
processThread = RunnerUtil.startApplication(pidFile);
info = RunnerUtil.readProcessInfo(pidFile);
runTests(info.pid);
processThread = RunnerUtil.startApplication();
runTests(processThread.getPid());
} catch (Throwable t) {
System.out.println("TestBasic got unexpected exception: " + t);
t.printStackTrace();
throw t;
} finally {
// Make sure the Application process is stopped.
RunnerUtil.stopApplication(info.shutdownPort, processThread);
RunnerUtil.stopApplication(processThread);
}
}
@ -78,7 +75,7 @@ public class BasicTests {
* The reason for running the tests in a separate process
* is that we need to modify the class path.
*/
private static void runTests(int pid) throws Throwable {
private static void runTests(long pid) throws Throwable {
final String sep = File.separator;
// Need to add jdk/lib/tools.jar to classpath.
@ -92,7 +89,7 @@ public class BasicTests {
"-classpath",
classpath,
"BasicTests$TestMain",
Integer.toString(pid),
Long.toString(pid),
testClassDir + "Agent.jar",
testClassDir + "BadAgent.jar",
testClassDir + "RedefineAgent.jar" };

View File

@ -23,7 +23,6 @@
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AttachNotSupportedException;
import java.util.Properties;
import java.io.File;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
@ -34,7 +33,7 @@ import jdk.testlibrary.ProcessThread;
* @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757
* @summary Basic unit tests for the VM attach mechanism.
* @library /lib/testlibrary
* @run build jdk.testlibrary.* Application Shutdown
* @run build jdk.testlibrary.* Application
* @run main PermissionTest
*
* Unit test for Attach API -
@ -51,20 +50,17 @@ public class PermissionTest {
* 4. Shut down the Application.
*/
public static void main(String args[]) throws Throwable {
final String pidFile ="TestPermission.Application.pid";
ProcessThread processThread = null;
RunnerUtil.ProcessInfo info = null;
try {
processThread = RunnerUtil.startApplication(pidFile);
info = RunnerUtil.readProcessInfo(pidFile);
runTests(info.pid);
processThread = RunnerUtil.startApplication();
runTests(processThread.getPid());
} catch (Throwable t) {
System.out.println("TestPermission got unexpected exception: " + t);
t.printStackTrace();
throw t;
} finally {
// Make sure the Application process is stopped.
RunnerUtil.stopApplication(info.shutdownPort, processThread);
RunnerUtil.stopApplication(processThread);
}
}
@ -72,7 +68,7 @@ public class PermissionTest {
* Runs the actual test the nested class TestMain.
* The test is run in a separate process because we need to add to the classpath.
*/
private static void runTests(int pid) throws Throwable {
private static void runTests(long pid) throws Throwable {
final String sep = File.separator;
// Need to add jdk/lib/tools.jar to classpath.
@ -88,7 +84,7 @@ public class PermissionTest {
"-Djava.security.manager",
String.format("-Djava.security.policy=%sjava.policy.deny", testSrc),
"PermissionTest$TestMain",
Integer.toString(pid),
Long.toString(pid),
"true" };
OutputAnalyzer output = ProcessTools.executeTestJvm(args);
output.shouldHaveExitValue(0);
@ -100,7 +96,7 @@ public class PermissionTest {
"-Djava.security.manager",
String.format("-Djava.security.policy=%sjava.policy.allow", testSrc),
"PermissionTest$TestMain",
Integer.toString(pid),
Long.toString(pid),
"false" };
output = ProcessTools.executeTestJvm(args);
output.shouldHaveExitValue(0);

View File

@ -25,10 +25,7 @@ import java.io.IOException;
import java.io.File;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.Utils;
import jdk.testlibrary.ProcessThread;
@ -49,12 +46,12 @@ public class RunnerUtil {
*
* The Application will write its pid and shutdownPort in the given outFile.
*/
public static ProcessThread startApplication(String outFile, String... additionalOpts) throws Throwable {
public static ProcessThread startApplication(String... additionalOpts) throws Throwable {
String classpath = System.getProperty("test.class.path", ".");
String[] myArgs = concat(additionalOpts, new String [] { "-Dattach.test=true", "-classpath", classpath, "Application", outFile });
String[] myArgs = concat(additionalOpts, new String [] { "-Dattach.test=true", "-classpath", classpath, "Application" });
String[] args = Utils.addTestJavaOpts(myArgs);
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
ProcessThread pt = new ProcessThread("runApplication", pb);
ProcessThread pt = new ProcessThread("runApplication", (line) -> line.equals(Application.READY_MSG), pb);
pt.start();
return pt;
}
@ -81,23 +78,16 @@ public class RunnerUtil {
*
* If the nice shutdown fails, then an Exception is thrown and the test should fail.
*
* @param port The shut down port.
* @param processThread The process to stop.
*/
public static void stopApplication(int port, ProcessThread processThread) throws Throwable {
public static void stopApplication(ProcessThread processThread) throws Throwable {
if (processThread == null) {
System.out.println("RunnerUtil.stopApplication ignored since proc is null");
return;
}
try {
System.out.println("RunnerUtil.stopApplication waiting to for shutdown");
OutputAnalyzer output = ProcessTools.executeTestJvm(
"-classpath",
System.getProperty("test.class.path", "."),
"Shutdown",
Integer.toString(port));
// Verify that both the Shutdown command and the Application finished ok.
output.shouldHaveExitValue(0);
System.out.println("RunnerUtil.stopApplication waiting for shutdown");
processThread.sendMessage(Application.SHUTDOWN_MSG);
processThread.joinAndThrow();
processThread.getOutput().shouldHaveExitValue(0);
} catch (Throwable t) {
@ -119,59 +109,6 @@ public class RunnerUtil {
}
}
/**
* Read process info for the running Application.
* The Application writes its info to a file with this format:
* shutdownPort=42994
* pid=19597
* done
*
* The final "done" is used to make sure the complete file has been written
* before we try to read it.
* This function will wait until the file is available.
*
* @param filename Path to file to read.
* @return The ProcessInfo containing pid and shutdownPort.
*/
public static ProcessInfo readProcessInfo(String filename) throws Throwable {
System.out.println("Reading port and pid from file: " + filename);
File file = new File(filename);
String content = null;
// Read file or wait for it to be created.
long startTime = System.currentTimeMillis();
long lastWarningTime = 0;
while (true) {
content = readFile(file);
if (content != null && content.indexOf("done") >= 0) {
break;
}
Thread.sleep(100);
long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
if (elapsedTime > lastWarningTime) {
lastWarningTime = elapsedTime;
System.out.println("Waited " + elapsedTime + " seconds for file.");
}
}
ProcessInfo info = new ProcessInfo();
// search for a line with format: key=nnn
Pattern pattern = Pattern.compile("(\\w*)=([0-9]+)\\r?\\n");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
String key = matcher.group(1);
int value = Integer.parseInt(matcher.group(2));
if ("pid".equals(key)) {
info.pid = value;
} else if ("shutdownPort".equals(key)) {
info.shutdownPort = value;
}
}
System.out.println("processInfo.pid:" + info.pid);
System.out.println("processInfo.shutdownPort:" + info.shutdownPort);
return info;
}
/**
* Read the content of a file.
* @param file The file to read.
@ -190,13 +127,4 @@ public class RunnerUtil {
throw e;
}
}
/**
* Helper class with info of the running Application.
*/
public static class ProcessInfo {
public int pid = -1;
public int shutdownPort = -1;
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2005, 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.
*/
/*
*
*
* Utility used by the unit tests for the attach mechanism. Connects to a
* given port which triggers the listener to shutdown.
*/
import java.net.Socket;
import java.net.InetSocketAddress;
import java.io.IOException;
public class Shutdown {
public static void main(String args[]) throws IOException {
int port = Integer.parseInt(args[0]);
System.out.println("Connecting to port " + port +
" to shutdown Application ...");
Socket s = new Socket();
s.connect( new InetSocketAddress(port) );
s.close();
}
}

View File

@ -40,7 +40,7 @@ import jdk.testlibrary.Utils;
* @test
* @summary Test for VirtualMachine.startManagementAgent and VirtualMachine.startLocalManagementAgent
* @library /lib/testlibrary
* @run build Application Shutdown
* @run build Application jdk.testlibrary.*
* @run main StartManagementAgent
*/
@ -51,20 +51,17 @@ import jdk.testlibrary.Utils;
*/
public class StartManagementAgent {
public static void main(String[] args) throws Throwable {
final String pidFile = "StartManagementAgent.Application.pid";
ProcessThread processThread = null;
RunnerUtil.ProcessInfo info = null;
try {
processThread = RunnerUtil.startApplication(pidFile);
info = RunnerUtil.readProcessInfo(pidFile);
runTests(info.pid);
processThread = RunnerUtil.startApplication();
runTests(processThread.getPid());
} catch (Throwable t) {
System.out.println("StartManagementAgent got unexpected exception: " + t);
t.printStackTrace();
throw t;
} finally {
// Make sure the Application process is stopped.
RunnerUtil.stopApplication(info.shutdownPort, processThread);
RunnerUtil.stopApplication(processThread);
}
}
@ -104,7 +101,7 @@ public class StartManagementAgent {
private static final int MAX_RETRIES = 10;
public static void runTests(int pid) throws Exception {
public static void runTests(long pid) throws Exception {
VirtualMachine vm = VirtualMachine.attach(""+pid);
try {

View File

@ -38,7 +38,7 @@ import jdk.testlibrary.ProcessThread;
* @bug 8033104
* @summary Test to make sure attach and jvmstat works correctly when java.io.tmpdir is set
* @library /lib/testlibrary
* @run build jdk.testlibrary.* Application Shutdown RunnerUtil
* @run build jdk.testlibrary.* Application RunnerUtil
* @run main/timeout=200 TempDirTest
*/
@ -90,22 +90,20 @@ public class TempDirTest {
final String pidFile = "TempDirTest.Application.pid-" + counter++;
ProcessThread processThread = null;
RunnerUtil.ProcessInfo info = null;
try {
String[] tmpDirArg = null;
if (targetTmpDir != null) {
tmpDirArg = new String[] {"-Djava.io.tmpdir=" + targetTmpDir};
}
processThread = RunnerUtil.startApplication(pidFile, tmpDirArg);
info = RunnerUtil.readProcessInfo(pidFile);
launchTests(info.pid, clientTmpDir);
processThread = RunnerUtil.startApplication(tmpDirArg);
launchTests(processThread.getPid(), clientTmpDir);
} catch (Throwable t) {
System.out.println("TempDirTest got unexpected exception: " + t);
t.printStackTrace();
throw t;
} finally {
// Make sure the Application process is stopped.
RunnerUtil.stopApplication(info.shutdownPort, processThread);
RunnerUtil.stopApplication(processThread);
}
elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
@ -119,7 +117,7 @@ public class TempDirTest {
* is that we need to modify the class path and
* the -Djava.io.tmpdir property.
*/
private static void launchTests(int pid, Path clientTmpDir) throws Throwable {
private static void launchTests(long pid, Path clientTmpDir) throws Throwable {
final String sep = File.separator;
// Need to add jdk/lib/tools.jar to classpath.
@ -139,7 +137,7 @@ public class TempDirTest {
"-classpath",
classpath,
"TempDirTest$TestMain",
Integer.toString(pid) });
Long.toString(pid) });
OutputAnalyzer output = ProcessTools.executeTestJvm(args);
output.shouldHaveExitValue(0);
}

View File

@ -23,11 +23,11 @@
package jdk.testlibrary;
import static jdk.testlibrary.Asserts.assertNotEquals;
import static jdk.testlibrary.Asserts.assertTrue;
import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
/**
* The helper class for starting and stopping {@link Process} in a separate thread.
@ -54,6 +54,29 @@ public class ProcessThread extends TestThread {
super(new ProcessRunnable(pb), threadName);
}
/**
* Creates a new {@code ProcessThread} object.
*
* @param threadName The name of thread
* @param waitfor A predicate to determine whether the target process has been initialized
* @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
*/
public ProcessThread(String threadName, Predicate<String> waitfor, String... cmd) {
super(new ProcessRunnable(new ProcessBuilder(cmd), threadName, waitfor), threadName);
}
/**
* Creates a new {@code ProcessThread} object.
*
* @param threadName The name of thread.
* @param waitfor A predicate to determine whether the target process has been initialized
* @param pb The ProcessBuilder to execute.
*/
public ProcessThread(String threadName, Predicate<String> waitfor, ProcessBuilder pb) {
super(new ProcessRunnable(pb, threadName, waitfor), threadName);
}
/**
* Stops {@link Process} started by {@code ProcessRunnable}.
*
@ -70,6 +93,18 @@ public class ProcessThread extends TestThread {
return ((ProcessRunnable) getRunnable()).getOutput();
}
/**
* Returns the PID associated with this process thread
* @return The PID associated with this process thread
*/
public long getPid() throws InterruptedException {
return ((ProcessRunnable)getRunnable()).getPid();
}
public void sendMessage(String message) throws InterruptedException {
((ProcessRunnable)getRunnable()).sendMessage(message);
}
/**
* {@link Runnable} interface for starting and stopping {@link Process}.
*/
@ -79,6 +114,8 @@ public class ProcessThread extends TestThread {
private final CountDownLatch latch;
private volatile Process process;
private volatile OutputAnalyzer output;
private final Predicate<String> waitfor;
private final String name;
/**
* Creates a new {@code ProcessRunnable} object.
@ -86,9 +123,21 @@ public class ProcessThread extends TestThread {
* @param pb The {@link ProcessBuilder} to run.
*/
public ProcessRunnable(ProcessBuilder pb) {
super();
this(pb, "", null);
}
/**
* Creates a new {@code ProcessRunnable} object.
*
* @param pb The {@link ProcessBuilder} to run.
* @param name An optional process name; may be null
* @param waitfor A predicate to determine whether the target process has been initialized; may be null
*/
public ProcessRunnable(ProcessBuilder pb, String name, Predicate<String> waitfor) {
this.processBuilder = pb;
this.latch = new CountDownLatch(1);
this.name = name;
this.waitfor = waitfor;
}
/**
@ -99,7 +148,9 @@ public class ProcessThread extends TestThread {
*/
@Override
public void xrun() throws Throwable {
this.process = processBuilder.start();
this.process = ProcessTools.startProcess(
name, processBuilder, waitfor, -1, TimeUnit.SECONDS
);
// Release when process is started
latch.countDown();
@ -138,6 +189,26 @@ public class ProcessThread extends TestThread {
public OutputAnalyzer getOutput() {
return output;
}
/**
* Returns the PID associated with this process runnable
* @return The PID associated with this process runnable
*/
public long getPid() throws InterruptedException {
return getProcess().getPid();
}
public void sendMessage(String message) throws InterruptedException {
try (PrintWriter pw = new PrintWriter(this.getProcess().getOutputStream())) {
pw.println(message);
pw.flush();
}
}
private Process getProcess() throws InterruptedException {
latch.await();
return process;
}
}
}

View File

@ -122,7 +122,6 @@ public class CustomLauncherTest {
);
final AtomicReference<String> port = new AtomicReference<>();
final AtomicReference<String> pid = new AtomicReference<>();
serverPrc = ProcessTools.startProcess(
"Launcher",
@ -130,12 +129,10 @@ public class CustomLauncherTest {
(String line) -> {
if (line.startsWith("port:")) {
port.set(line.split("\\:")[1]);
} else if (line.startsWith("pid:")) {
pid.set(line.split("\\:")[1]);
} else if (line.startsWith("waiting")) {
} else if (line.startsWith("waiting")) {
return true;
}
return false;
}
return false;
},
5,
TimeUnit.SECONDS
@ -143,7 +140,7 @@ public class CustomLauncherTest {
System.out.println("Attaching test manager:");
System.out.println("=========================");
System.out.println(" PID : " + pid.get());
System.out.println(" PID : " + serverPrc.getPid());
System.out.println(" shutdown port : " + port.get());
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
@ -156,7 +153,7 @@ public class CustomLauncherTest {
File.separator +
"tools.jar",
"TestManager",
pid.get(),
String.valueOf(serverPrc.getPid()),
port.get(),
"true"
);

View File

@ -109,7 +109,6 @@ public class LocalManagementTest {
Process serverPrc = null, clientPrc = null;
try {
final AtomicReference<String> port = new AtomicReference<>();
final AtomicReference<String> pid = new AtomicReference<>();
serverPrc = ProcessTools.startProcess(
"TestApplication(" + testId + ")",
@ -117,12 +116,10 @@ public class LocalManagementTest {
(String line) -> {
if (line.startsWith("port:")) {
port.set(line.split("\\:")[1]);
} else if (line.startsWith("pid:")) {
pid.set(line.split("\\:")[1]);
} else if (line.startsWith("waiting")) {
return true;
}
return false;
} else if (line.startsWith("waiting")) {
return true;
}
return false;
},
5,
TimeUnit.SECONDS
@ -130,7 +127,7 @@ public class LocalManagementTest {
System.out.println("Attaching test manager:");
System.out.println("=========================");
System.out.println(" PID : " + pid.get());
System.out.println(" PID : " + serverPrc.getPid());
System.out.println(" shutdown port : " + port.get());
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
@ -143,7 +140,7 @@ public class LocalManagementTest {
File.separator +
"tools.jar",
"TestManager",
pid.get(),
String.valueOf(serverPrc.getPid()),
port.get(),
"true"
);

View File

@ -26,16 +26,13 @@
*
* A test "application" used by unit tests -
* LocalManagementTest.java, CustomLauncherTest.java.
* This application binds to some random port, prints its pid and
* the port number to standard output, waits for somebody to connect,
* and then shuts down.
* This application binds to some random port, prints the port number
* to standard output, waits for somebody to connect, and then shuts down.
*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import jdk.testlibrary.ProcessTools;
public class TestApplication {
public static void main(String[] args) throws IOException {
// Some tests require the application to exit immediately
@ -47,16 +44,8 @@ public class TestApplication {
ServerSocket ss = new ServerSocket(0);
int port = ss.getLocalPort();
int pid = -1;
try {
pid = ProcessTools.getProcessId();
} catch (Exception e) {
e.printStackTrace();
}
// signal test that we are started - do not remove these lines!!
System.out.println("port:" + port);
System.out.println("pid:" + pid);
System.out.println("waiting for the manager ...");
System.out.flush();

View File

@ -31,7 +31,6 @@ public class JMXStartStopDoSomething {
}
public static void main(String args[]) throws Exception {
System.out.println("pid:" + ProcessTools.getProcessId());
System.out.println("main enter");
System.out.flush();
doSomething();

View File

@ -134,13 +134,13 @@ public class JMXStartStopTest {
}
private static void testConnectLocal(int pid)
private static void testConnectLocal(long pid)
throws Exception {
String jmxUrlStr = null;
try {
jmxUrlStr = sun.management.ConnectorAddressLink.importFrom(pid);
jmxUrlStr = sun.management.ConnectorAddressLink.importFrom((int)pid);
dbg_print("Local Service URL: " +jmxUrlStr);
if ( jmxUrlStr == null ) {
throw new Exception("No Service URL. Local agent not started?");
@ -318,7 +318,7 @@ public class JMXStartStopTest {
private final ProcessBuilder pb;
private final String name;
private final AtomicBoolean started = new AtomicBoolean(false);
private volatile int pid = -1;
private volatile long pid = -1;
public Something(ProcessBuilder pb, String name) {
this.pb = pb;
@ -331,15 +331,11 @@ public class JMXStartStopTest {
p = ProcessTools.startProcess(
"JMXStartStopDoSomething",
pb,
(line) -> {
if (line.toLowerCase().startsWith("pid:")) {
pid = Integer.parseInt(line.split("\\:")[1]);
}
return line.equals("main enter");
},
(line) -> line.equals("main enter"),
5,
TimeUnit.SECONDS
);
pid = p.getPid();
} catch (TimeoutException e) {
p.destroy();
p.waitFor();
@ -348,7 +344,7 @@ public class JMXStartStopTest {
}
}
public int getPid() {
public long getPid() {
return pid;
}

View File

@ -42,14 +42,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class JStatInterval {
private static final String PID = "PID";
private static final String READY = "READY";
private static final String ERROR = "!ERROR";
public static class Application {
public static void main(String[] args) {
try {
System.out.println(PID + ":" + ProcessTools.getProcessId());
System.out.println(READY);
System.out.flush();
int exitCode = System.in.read();
@ -69,15 +67,12 @@ public class JStatInterval {
"-XX:+UsePerfData",
Application.class.getName()
);
AtomicInteger pid = new AtomicInteger(-1);
AtomicBoolean error = new AtomicBoolean(false);
Process app = ProcessTools.startProcess(
"application",
pb,
line -> {
if (line.startsWith(PID)) {
pid.set(Integer.parseInt(line.split("\\:")[1]));
} else if (line.equals(READY)) {
if (line.equals(READY)) {
return true;
} else if (line.equals(ERROR)) {
error.set(true);
@ -92,7 +87,7 @@ public class JStatInterval {
throw new Error("Unable to start the monitored application.");
}
String pidStr = String.valueOf(pid.get());
String pidStr = String.valueOf(app.getPid());
JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jstat");
l.addToolArg("-compiler");
l.addToolArg(pidStr);

View File

@ -22,12 +22,12 @@
*/
import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Arrays;
import java.util.regex.Pattern;
import static jdk.testlibrary.Asserts.*;
import jdk.testlibrary.JDKToolLauncher;
@ -69,7 +69,7 @@ public final class JstatdTest {
private boolean useDefaultPort = true;
private String port;
private String serverName;
private String jstatdPid;
private Long jstatdPid;
private boolean withExternalRegistry = false;
public void setServerName(String serverName) {
@ -84,67 +84,26 @@ public final class JstatdTest {
this.withExternalRegistry = withExternalRegistry;
}
/**
* Parse pid from jps output
*/
private String parsePid(String tool, OutputAnalyzer output) throws Exception {
String[] lines = output.getOutput().split(Utils.NEW_LINE);
String pid = null;
int count = 0;
String processName = tool;
if (tool == "rmiregistry") {
processName = "registryimpl";
}
private Long waitOnTool(ProcessThread thread) throws Throwable {
long pid = thread.getPid();
Pattern toolInJpsPattern =
Pattern.compile("^\\d+\\s{1}" + processName + "\\s{1}.*-dparent\\.pid\\." + ProcessTools.getProcessId() + ".*");
for (String line : lines) {
if (toolInJpsPattern.matcher(line.toLowerCase()).matches()) {
pid = line.split(" ")[0];
count++;
Throwable t = thread.getUncaught();
if (t != null) {
if (t.getMessage().contains(
"java.rmi.server.ExportException: Port already in use")) {
System.out.println("Port already in use. Trying to restart with a new one...");
Thread.sleep(100);
return null;
} else {
// Something unexpected has happened
throw new Throwable(t);
}
}
if (count > 1) {
throw new Exception("Expected one " + tool
+ " process, got " + count + ". Test will be canceled.");
}
System.out.println(thread.getName() + " pid: " + pid);
return pid;
}
private String getToolPid(String tool)
throws Exception {
OutputAnalyzer output = runJps();
return parsePid(tool, output);
}
private String waitOnTool(String tool, TestThread thread) throws Throwable {
while (true) {
String pid = getToolPid(tool);
if (pid != null) {
System.out.println(tool + " pid: " + pid);
return pid;
}
Throwable t = thread.getUncaught();
if (t != null) {
if (t.getMessage().contains(
"java.rmi.server.ExportException: Port already in use")) {
System.out.println("Port already in use. Trying to restart with a new one...");
Thread.sleep(100);
return null;
} else {
// Something unexpected has happened
throw new Throwable(t);
}
}
System.out.println("Waiting until " + tool + " is running...");
Thread.sleep(100);
}
}
private void log(String caption, String... cmd) {
System.out.println(Utils.NEW_LINE + caption + ":");
System.out.println(Arrays.toString(cmd).replace(",", ""));
@ -180,12 +139,29 @@ public final class JstatdTest {
log("Start jps", cmd);
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
OutputAnalyzer output = waitForJstatdRMI(processBuilder);
System.out.println(output.getOutput());
return output;
}
private OutputAnalyzer waitForJstatdRMI(ProcessBuilder pb) throws IOException, InterruptedException {
OutputAnalyzer output = new OutputAnalyzer(pb.start());
while (output.getExitValue() != 0) {
String out = output.getOutput();
if (out.contains("RMI Registry not available") ||
out.contains("RMI Server JStatRemoteHost not available")) {
Thread.sleep(100);
output = new OutputAnalyzer(pb.start());
} else {
output.shouldHaveExitValue(0);
}
}
return output;
}
/**
* Verifies output form jps contains pids and programs' name information.
* The function will discard any lines that come before the first line with pid.
@ -235,7 +211,7 @@ public final class JstatdTest {
log("Start jstat", cmd);
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
OutputAnalyzer output = waitForJstatdRMI(processBuilder);
System.out.println(output.getOutput());
return output;
@ -323,7 +299,7 @@ public final class JstatdTest {
try {
jstatdThread.start();
// Make sure jstatd is up and running
jstatdPid = waitOnTool("jstatd", jstatdThread);
jstatdPid = waitOnTool(jstatdThread);
if (jstatdPid == null) {
// The port is already in use. Cancel and try with new one.
jstatdThread.stopProcess();
@ -344,7 +320,7 @@ public final class JstatdTest {
try {
while (jstatdThread == null) {
if (!useDefaultPort || withExternalRegistry) {
port = Integer.toString(Utils.getFreePort());
port = String.valueOf(Utils.getFreePort());
}
if (withExternalRegistry) {