8048193: [tests] Replace JPS and stdout based PID retrieval by Process.getPid()
authorjbachorik
Tue, 01 Jul 2014 15:00:33 +0200
changeset 25182 1f6766bac82c
parent 25181 216e0899f503
child 25183 d3ff4a191db3
8048193: [tests] Replace JPS and stdout based PID retrieval by Process.getPid() Reviewed-by: sla
jdk/test/com/sun/tools/attach/Application.java
jdk/test/com/sun/tools/attach/BasicTests.java
jdk/test/com/sun/tools/attach/PermissionTest.java
jdk/test/com/sun/tools/attach/RunnerUtil.java
jdk/test/com/sun/tools/attach/Shutdown.java
jdk/test/com/sun/tools/attach/StartManagementAgent.java
jdk/test/com/sun/tools/attach/TempDirTest.java
jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java
jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java
jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
jdk/test/sun/management/jmxremote/bootstrap/TestApplication.java
jdk/test/sun/management/jmxremote/startstop/JMXStartStopDoSomething.java
jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java
jdk/test/sun/tools/jstat/JStatInterval.java
jdk/test/sun/tools/jstatd/JstatdTest.java
--- a/jdk/test/com/sun/tools/attach/Application.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/com/sun/tools/attach/Application.java	Tue Jul 01 15:00:33 2014 +0200
@@ -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 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];
+    public static final String READY_MSG="ready";
+    public static final String SHUTDOWN_MSG="shutdown";
 
-        ServerSocket ss = new ServerSocket(0);
-        int port = ss.getLocalPort();
-        int pid = ProcessTools.getProcessId();
-
-        System.out.println("shutdownPort=" + port);
-        System.out.println("pid=" + pid);
+    public static void main(String args[]) throws Exception {
+        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();
     }
 }
--- a/jdk/test/com/sun/tools/attach/BasicTests.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/com/sun/tools/attach/BasicTests.java	Tue Jul 01 15:00:33 2014 +0200
@@ -38,7 +38,7 @@
  * @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 @@
      * 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 @@
      * 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 @@
             "-classpath",
             classpath,
             "BasicTests$TestMain",
-            Integer.toString(pid),
+            Long.toString(pid),
             testClassDir + "Agent.jar",
             testClassDir + "BadAgent.jar",
             testClassDir + "RedefineAgent.jar" };
--- a/jdk/test/com/sun/tools/attach/PermissionTest.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/com/sun/tools/attach/PermissionTest.java	Tue Jul 01 15:00:33 2014 +0200
@@ -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 @@
  * @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 @@
      * 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 @@
      * 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 @@
             "-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 @@
             "-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);
--- a/jdk/test/com/sun/tools/attach/RunnerUtil.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/com/sun/tools/attach/RunnerUtil.java	Tue Jul 01 15:00:33 2014 +0200
@@ -25,10 +25,7 @@
 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 @@
      *
      * 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 @@
      *
      * 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) {
@@ -120,59 +110,6 @@
     }
 
     /**
-     * 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.
      * @return The file content or null if file does not exists.
@@ -190,13 +127,4 @@
             throw e;
         }
     }
-
-    /**
-     * Helper class with info of the running Application.
-     */
-    public static class ProcessInfo {
-        public int pid = -1;
-        public int shutdownPort = -1;
-    }
-
 }
--- a/jdk/test/com/sun/tools/attach/Shutdown.java	Tue Jul 01 11:47:36 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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();
-    }
-}
--- a/jdk/test/com/sun/tools/attach/StartManagementAgent.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/com/sun/tools/attach/StartManagementAgent.java	Tue Jul 01 15:00:33 2014 +0200
@@ -40,7 +40,7 @@
  * @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 @@
  */
 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 @@
 
     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 {
 
--- a/jdk/test/com/sun/tools/attach/TempDirTest.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/com/sun/tools/attach/TempDirTest.java	Tue Jul 01 15:00:33 2014 +0200
@@ -38,7 +38,7 @@
  * @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 @@
 
         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 @@
      * 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 @@
                     "-classpath",
                     classpath,
                     "TempDirTest$TestMain",
-                    Integer.toString(pid) });
+                    Long.toString(pid) });
         OutputAnalyzer output = ProcessTools.executeTestJvm(args);
         output.shouldHaveExitValue(0);
     }
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java	Tue Jul 01 15:00:33 2014 +0200
@@ -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 @@
         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}.
      *
@@ -71,6 +94,18 @@
     }
 
     /**
+    * 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}.
      */
     static class ProcessRunnable extends XRun {
@@ -79,6 +114,8 @@
         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 @@
          * @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 @@
          */
         @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 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;
+        }
     }
 
 }
--- a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java	Tue Jul 01 15:00:33 2014 +0200
@@ -122,7 +122,6 @@
             );
 
             final AtomicReference<String> port = new AtomicReference<>();
-            final AtomicReference<String> pid = new AtomicReference<>();
 
             serverPrc = ProcessTools.startProcess(
                 "Launcher",
@@ -130,12 +129,10 @@
                 (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 @@
 
             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 @@
                     File.separator +
                     "tools.jar",
                 "TestManager",
-                pid.get(),
+                String.valueOf(serverPrc.getPid()),
                 port.get(),
                 "true"
             );
--- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java	Tue Jul 01 15:00:33 2014 +0200
@@ -109,7 +109,6 @@
         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 @@
                 (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 @@
 
             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 @@
                     File.separator +
                     "tools.jar",
                 "TestManager",
-                pid.get(),
+                String.valueOf(serverPrc.getPid()),
                 port.get(),
                 "true"
             );
--- a/jdk/test/sun/management/jmxremote/bootstrap/TestApplication.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/management/jmxremote/bootstrap/TestApplication.java	Tue Jul 01 15:00:33 2014 +0200
@@ -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 @@
         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();
 
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopDoSomething.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopDoSomething.java	Tue Jul 01 15:00:33 2014 +0200
@@ -31,7 +31,6 @@
     }
 
     public static void main(String args[]) throws Exception {
-        System.out.println("pid:" + ProcessTools.getProcessId());
         System.out.println("main enter");
         System.out.flush();
         doSomething();
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Tue Jul 01 15:00:33 2014 +0200
@@ -134,13 +134,13 @@
     }
 
 
-    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 @@
         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 @@
                     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 int getPid() {
+        public long getPid() {
             return pid;
         }
 
--- a/jdk/test/sun/tools/jstat/JStatInterval.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/tools/jstat/JStatInterval.java	Tue Jul 01 15:00:33 2014 +0200
@@ -42,14 +42,12 @@
 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 @@
             "-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 @@
             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);
--- a/jdk/test/sun/tools/jstatd/JstatdTest.java	Tue Jul 01 11:47:36 2014 +0200
+++ b/jdk/test/sun/tools/jstatd/JstatdTest.java	Tue Jul 01 15:00:33 2014 +0200
@@ -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 @@
     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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         try {
             while (jstatdThread == null) {
                 if (!useDefaultPort || withExternalRegistry) {
-                    port = Integer.toString(Utils.getFreePort());
+                    port = String.valueOf(Utils.getFreePort());
                 }
 
                 if (withExternalRegistry) {