8044135: Add API to start JMX agent from attach framework
authorsla
Wed, 11 Jun 2014 15:47:53 +0200
changeset 24870 5d567113d043
parent 24869 6cdd5aa7e259
child 24871 224e298c3978
8044135: Add API to start JMX agent from attach framework Reviewed-by: alanb
jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java
jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java
jdk/test/com/sun/tools/attach/SimpleProvider.java
jdk/test/com/sun/tools/attach/StartManagementAgent.java
jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java
jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
jdk/test/sun/management/jmxremote/bootstrap/TestManager.java
jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java
--- a/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java	Wed Jun 11 15:47:53 2014 +0200
@@ -76,16 +76,10 @@
  *      // attach to target VM
  *      VirtualMachine vm = VirtualMachine.attach("2177");
  *
- *      // get system properties in target VM
- *      Properties props = vm.getSystemProperties();
- *
- *      // construct path to management agent
- *      String home = props.getProperty("java.home");
- *      String agent = home + File.separator + "lib" + File.separator
- *          + "management-agent.jar";
- *
- *      // load agent into target VM
- *      vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000");
+ *      // start management agent
+ *      Properties props = new Properties();
+ *      props.put("com.sun.management.jmxremote.port", "5000");
+ *      vm.startManagementAgent(props);
  *
  *      // detach
  *      vm.detach();
@@ -93,9 +87,9 @@
  * </pre>
  *
  * <p> In this example we attach to a Java virtual machine that is identified by
- * the process identifier <code>2177</code>. The system properties from the target
- * VM are then used to construct the path to a <i>management agent</i> which is then
- * loaded into the target VM. Once loaded the client detaches from the target VM. </p>
+ * the process identifier <code>2177</code>. Then the JMX management agent is
+ * started in the target process using the supplied arguments. Finally, the
+ * client detaches from the target VM. </p>
  *
  * <p> A VirtualMachine is safe for use by multiple concurrent threads. </p>
  *
@@ -611,6 +605,68 @@
     public abstract Properties getAgentProperties() throws IOException;
 
     /**
+     * Starts the JMX management agent in the target virtual machine.
+     *
+     * <p> The configuration properties are the same as those specified on
+     * the command line when starting the JMX management agent. In the same
+     * way as on the command line, you need to specify at least the
+     * {@code com.sun.management.jmxremote.port} property.
+     *
+     * <p> See the online documentation for <a
+     * href="../../../../../../../../technotes/guides/management/agent.html">
+     * Monitoring and Management Using JMX Technology</a> for further details.
+     *
+     * @param   agentProperties
+     *          A Properties object containing the configuration properties
+     *          for the agent.
+     *
+     * @throws  AttachOperationFailedException
+     *          If the target virtual machine is unable to complete the
+     *          attach operation. A more specific error message will be
+     *          given by {@link AttachOperationFailedException#getMessage()}.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs, a communication error for example,
+     *          that cannot be identified as an error to indicate that the
+     *          operation failed in the target VM.
+     *
+     * @throws  IllegalArgumentException
+     *          If keys or values in agentProperties are invalid.
+     *
+     * @throws  NullPointerException
+     *          If agentProperties is null.
+     *
+     * @since   1.9
+     */
+    public abstract void startManagementAgent(Properties agentProperties) throws IOException;
+
+    /**
+     * Starts the local JMX management agent in the target virtual machine.
+     *
+     * <p> See the online documentation for <a
+     * href="../../../../../../../../technotes/guides/management/agent.html">
+     * Monitoring and Management Using JMX Technology</a> for further details.
+     *
+     * @return  The String representation of the local connector's service address.
+     *          The value can be parsed by the
+     *          {@link javax.management.remote.JMXServiceURL#JMXServiceURL(String)}
+     *          constructor.
+     *
+     * @throws  AttachOperationFailedException
+     *          If the target virtual machine is unable to complete the
+     *          attach operation. A more specific error message will be
+     *          given by {@link AttachOperationFailedException#getMessage()}.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs, a communication error for example,
+     *          that cannot be identified as an error to indicate that the
+     *          operation failed in the target VM.
+     *
+     * @since   1.9
+     */
+    public abstract String startLocalManagementAgent() throws IOException;
+
+    /**
      * Returns a hash-code value for this VirtualMachine. The hash
      * code is based upon the VirtualMachine's components, and satifies
      * the general contract of the {@link java.lang.Object#hashCode()
--- a/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Wed Jun 11 15:47:53 2014 +0200
@@ -33,7 +33,7 @@
 import java.io.InputStream;
 import java.io.IOException;
 import java.util.Properties;
-import java.util.Map;
+import java.util.stream.Collectors;
 
 /*
  * The HotSpot implementation of com.sun.tools.attach.VirtualMachine.
@@ -161,6 +161,50 @@
         return props;
     }
 
+    private static final String MANAGMENT_PREFIX = "com.sun.management.";
+
+    private static boolean checkedKeyName(Object key) {
+        if (!(key instanceof String)) {
+            throw new IllegalArgumentException("Invalid option (not a String): "+key);
+        }
+        if (!((String)key).startsWith(MANAGMENT_PREFIX)) {
+            throw new IllegalArgumentException("Invalid option: "+key);
+        }
+        return true;
+    }
+
+    private static String stripKeyName(Object key) {
+        return ((String)key).substring(MANAGMENT_PREFIX.length());
+    }
+
+    @Override
+    public void startManagementAgent(Properties agentProperties) throws IOException {
+        if (agentProperties == null) {
+            throw new NullPointerException("agentProperties cannot be null");
+        }
+        // Convert the arguments into arguments suitable for the Diagnostic Command:
+        // "ManagementAgent.start jmxremote.port=5555 jmxremote.authenticate=false"
+        String args = agentProperties.entrySet().stream()
+            .filter(entry -> checkedKeyName(entry.getKey()))
+            .map(entry -> stripKeyName(entry.getKey()) + "=" + escape(entry.getValue()))
+            .collect(Collectors.joining(" "));
+        executeJCmd("ManagementAgent.start " + args);
+    }
+
+    private String escape(Object arg) {
+        String value = arg.toString();
+        if (value.contains(" ")) {
+            return "'" + value + "'";
+        }
+        return value;
+    }
+
+    @Override
+    public String startLocalManagementAgent() throws IOException {
+        executeJCmd("ManagementAgent.start_local");
+        return getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
+    }
+
     // --- HotSpot specific methods ---
 
     // same as SIGQUIT
--- a/jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java	Wed Jun 11 15:47:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -32,8 +32,6 @@
 // Sun specific
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
-import com.sun.tools.attach.AgentInitializationException;
-import com.sun.tools.attach.AgentLoadException;
 import com.sun.tools.attach.AttachNotSupportedException;
 
 // Sun private
@@ -238,35 +236,7 @@
             throw ioe;
         }
 
-        String home = vm.getSystemProperties().getProperty("java.home");
-
-        // Normally in ${java.home}/jre/lib/management-agent.jar but might
-        // be in ${java.home}/lib in build environments.
-
-        String agent = home + File.separator + "jre" + File.separator +
-                           "lib" + File.separator + "management-agent.jar";
-        File f = new File(agent);
-        if (!f.exists()) {
-            agent = home + File.separator +  "lib" + File.separator +
-                        "management-agent.jar";
-            f = new File(agent);
-            if (!f.exists()) {
-                throw new IOException("Management agent not found");
-            }
-        }
-
-        agent = f.getCanonicalPath();
-        try {
-            vm.loadAgent(agent, "com.sun.management.jmxremote");
-        } catch (AgentLoadException x) {
-            IOException ioe = new IOException(x.getMessage());
-            ioe.initCause(x);
-            throw ioe;
-        } catch (AgentInitializationException x) {
-            IOException ioe = new IOException(x.getMessage());
-            ioe.initCause(x);
-            throw ioe;
-        }
+        vm.startLocalManagementAgent();
 
         // get the connector address
         Properties agentProps = vm.getAgentProperties();
--- a/jdk/test/com/sun/tools/attach/SimpleProvider.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/test/com/sun/tools/attach/SimpleProvider.java	Wed Jun 11 15:47:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -100,4 +100,12 @@
 
     public void dataDumpRequest() throws IOException {
     }
+
+    public String startLocalManagementAgent() {
+        return null;
+    }
+
+    public void startManagementAgent(Properties agentProperties) {
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/StartManagementAgent.java	Wed Jun 11 15:47:53 2014 +0200
@@ -0,0 +1,211 @@
+/*
+ * 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 com.sun.tools.attach.AttachOperationFailedException;
+import com.sun.tools.attach.VirtualMachine;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.Properties;
+import java.util.HashMap;
+
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+
+import jdk.testlibrary.ProcessThread;
+import jdk.testlibrary.Utils;
+
+/*
+ * @test
+ * @summary Test for VirtualMachine.startManagementAgent and VirtualMachine.startLocalManagementAgent
+ * @library /lib/testlibrary
+ * @run build Application Shutdown
+ * @run main StartManagementAgent
+ */
+
+/*
+ * This test is not meant to test all possible configuration parameters to
+ * the JMX agent, there are other tests for that. This test makes sure it is
+ * possible to start the agent via attach.
+ */
+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);
+        } 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);
+        }
+    }
+
+    private static void basicTests(VirtualMachine vm) throws Exception {
+
+        // Try calling with null argument
+        boolean exception = false;
+        try {
+            vm.startManagementAgent(null);
+        } catch (NullPointerException e) {
+            exception = true;
+        }
+        if (!exception) {
+            throw new Exception("startManagementAgent(null) should throw NPE");
+        }
+
+        // Try calling with a property value with a space in it
+        Properties p = new Properties();
+        File f = new File("file with space");
+        try (FileWriter fw = new FileWriter(f)) {
+            fw.write("com.sun.management.jmxremote.port=apa");
+        }
+        p.put("com.sun.management.config.file", f.getAbsolutePath());
+        try {
+            vm.startManagementAgent(p);
+        } catch(AttachOperationFailedException ex) {
+            // We expect parsing of "apa" above to fail, but if the file path
+            // can't be read we get a different exception message
+            if (!ex.getMessage().contains("java.lang.NumberFormatException")) {
+                throw ex;
+            }
+        }
+    }
+
+    private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
+        "com.sun.management.jmxremote.localConnectorAddress";
+
+    private static final int MAX_RETRIES = 10;
+
+    public static void runTests(int pid) throws Exception {
+        VirtualMachine vm = VirtualMachine.attach(""+pid);
+        try {
+
+            basicTests(vm);
+
+            testLocalAgent(vm);
+
+            // we retry the remote case several times in case the error
+            // was caused by a port conflict
+            int i = 0;
+            boolean success = false;
+            do {
+                try {
+                    System.err.println("Trying remote agent. Try #" + i);
+                    testRemoteAgent(vm);
+                    success = true;
+                } catch(Exception ex) {
+                    System.err.println("testRemoteAgent failed with exception:");
+                    ex.printStackTrace();
+                    System.err.println("Retrying.");
+                }
+                i++;
+            } while(!success && i < MAX_RETRIES);
+            if (!success) {
+                throw new Exception("testRemoteAgent failed after " + MAX_RETRIES + " tries");
+            }
+        } finally {
+            vm.detach();
+        }
+    }
+
+    public static void testLocalAgent(VirtualMachine vm) throws Exception {
+        Properties agentProps = vm.getAgentProperties();
+        String address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+        if (address != null) {
+            throw new Exception("Local management agent already started");
+        }
+
+        String result = vm.startLocalManagementAgent();
+
+        // try to parse the return value as a JMXServiceURL
+        new JMXServiceURL(result);
+
+        agentProps = vm.getAgentProperties();
+        address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+        if (address == null) {
+            throw new Exception("Local management agent could not be started");
+        }
+    }
+
+    public static void testRemoteAgent(VirtualMachine vm) throws Exception {
+        int port = Utils.getFreePort();
+
+        // try to connect - should fail
+        tryConnect(port, false);
+
+        // start agent
+        System.out.println("Starting agent on port: " + port);
+        Properties mgmtProps = new Properties();
+        mgmtProps.put("com.sun.management.jmxremote.port", port);
+        mgmtProps.put("com.sun.management.jmxremote.authenticate", "false");
+        mgmtProps.put("com.sun.management.jmxremote.ssl", "false");
+        vm.startManagementAgent(mgmtProps);
+
+        // try to connect - should work
+        tryConnect(port, true);
+
+        // try to start again - should fail
+        boolean exception = false;
+        try {
+            vm.startManagementAgent(mgmtProps);
+        } catch(AttachOperationFailedException ex) {
+            // expected
+            exception = true;
+        }
+        if (!exception) {
+            throw new Exception("Expected the second call to vm.startManagementAgent() to fail");
+        }
+    }
+
+    private static void tryConnect(int port, boolean shouldSucceed) throws Exception {
+        String jmxUrlStr =
+            String.format(
+                "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi",
+                port);
+        JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
+        HashMap<String, ?> env = new HashMap<>();
+
+        boolean succeeded;
+        try {
+            JMXConnector c = JMXConnectorFactory.connect(url, env);
+            c.getMBeanServerConnection();
+            succeeded = true;
+        } catch(Exception ex) {
+            succeeded = false;
+        }
+        if (succeeded && !shouldSucceed) {
+            throw new Exception("Could connect to agent, but should not have been possible");
+        }
+        if (!succeeded && shouldSucceed) {
+            throw new Exception("Could not connect to agent");
+        }
+    }
+}
--- a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java	Wed Jun 11 15:47:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -143,9 +143,12 @@
                 String vmid = name.substring(0, name.indexOf("@"));
                 System.out.println("vmid = " + vmid);
                 VirtualMachine vm = VirtualMachine.attach(vmid);
-                String agent = vm.getSystemProperties().getProperty("java.home") +
-                        File.separator + "lib" + File.separator + "management-agent.jar";
-                vm.loadAgent(agent, "com.sun.management.jmxremote.port=0,com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false");
+                Properties p = new Properties();
+                p.put("com.sun.management.jmxremote.port", "0");
+                p.put("com.sun.management.jmxremote.authenticate", "false");
+                p.put("com.sun.management.jmxremote.ssl", "false");
+                vm.startManagementAgent(p);
+                vm.startLocalManagementAgent();
                 vm.detach();
                 String localAddress2 = ConnectorAddressLink.importFrom(0);
                 if (localAddress2 == null) {
--- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java	Wed Jun 11 15:47:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,13 +22,8 @@
  */
 
 import java.io.File;
-import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -47,19 +42,12 @@
  */
 
 import jdk.testlibrary.ProcessTools;
-import jdk.testlibrary.Utils;
 
 public class LocalManagementTest {
     private static final String TEST_CLASSPATH = System.getProperty("test.class.path");
     private static final String TEST_JDK = System.getProperty("test.jdk");
-    private static int MAX_GET_FREE_PORT_TRIES = 10;
 
     public static void main(String[] args) throws Exception {
-        try {
-            MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10"));
-        } catch (NumberFormatException ex) {
-        }
-
         int failures = 0;
         for(Method m : LocalManagementTest.class.getDeclaredMethods()) {
             if (Modifier.isStatic(m.getModifiers()) &&
@@ -84,110 +72,27 @@
         }
     }
 
+    @SuppressWarnings("unused")
     private static boolean test1() throws Exception {
         return doTest("1", "-Dcom.sun.management.jmxremote");
     }
 
-    private static boolean test2() throws Exception {
-        Path agentPath = findAgent();
-        if (agentPath != null) {
-            String agent = agentPath.toString();
-            return doTest("2", "-javaagent:" + agent);
-        } else {
-            return false;
-        }
-    }
-
     /**
      * no args (blank) - manager should attach and start agent
      */
+    @SuppressWarnings("unused")
     private static boolean test3() throws Exception {
         return doTest("3", null);
     }
 
     /**
-     * sanity check arguments to management-agent.jar
-     */
-    private static boolean test4() throws Exception {
-        Path agentPath = findAgent();
-        if (agentPath != null) {
-
-            for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; ++i) {
-                ProcessBuilder builder = ProcessTools.createJavaProcessBuilder(
-                        "-javaagent:" + agentPath.toString() +
-                                "=com.sun.management.jmxremote.port=" + Utils.getFreePort() + "," +
-                                "com.sun.management.jmxremote.authenticate=false," +
-                                "com.sun.management.jmxremote.ssl=false",
-                        "-cp",
-                        TEST_CLASSPATH,
-                        "TestApplication",
-                        "-exit"
-                );
-
-                Process prc = null;
-                final AtomicReference<Boolean> isBindExceptionThrown = new AtomicReference<>();
-                isBindExceptionThrown.set(new Boolean(false));
-                try {
-                    prc = ProcessTools.startProcess(
-                            "TestApplication",
-                            builder,
-                            (String line) -> {
-                                if (line.contains("Exception thrown by the agent : " +
-                                        "java.rmi.server.ExportException: Port already in use")) {
-                                    isBindExceptionThrown.set(new Boolean(true));
-                                }
-                            });
-
-                    prc.waitFor();
-
-                    if (prc.exitValue() == 0) {
-                        return true;
-                    }
-
-                    if (isBindExceptionThrown.get().booleanValue()) {
-                        System.out.println("'Port already in use' error detected. Try again");
-                    } else {
-                        return false;
-                    }
-                } finally {
-                    if (prc != null) {
-                        prc.destroy();
-                        prc.waitFor();
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
      * use DNS-only name service
      */
+    @SuppressWarnings("unused")
     private static boolean test5() throws Exception {
         return doTest("5", "-Dsun.net.spi.namservice.provider.1=\"dns,sun\"");
     }
 
-    private static Path findAgent() {
-        FileSystem FS = FileSystems.getDefault();
-        Path agentPath = FS.getPath(
-            TEST_JDK, "jre", "lib", "management-agent.jar"
-        );
-        if (!isFileOk(agentPath)) {
-            agentPath = FS.getPath(
-                TEST_JDK, "lib", "management-agent.jar"
-            );
-        }
-        if (!isFileOk(agentPath)) {
-            System.err.println("Can not locate management-agent.jar");
-            return null;
-        }
-        return agentPath;
-    }
-
-    private static boolean isFileOk(Path path) {
-        return Files.isRegularFile(path) && Files.isReadable(path);
-    }
-
     private static boolean doTest(String testId, String arg) throws Exception {
         List<String> args = new ArrayList<>();
         args.add("-cp");
@@ -267,4 +172,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
--- a/jdk/test/sun/management/jmxremote/bootstrap/TestManager.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/test/sun/management/jmxremote/bootstrap/TestManager.java	Wed Jun 11 15:47:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -40,7 +40,6 @@
 import static java.lang.management.ManagementFactory.*;
 import java.net.Socket;
 import java.net.InetSocketAddress;
-import java.io.File;
 import java.io.IOException;
 
 // Sun specific
@@ -55,28 +54,8 @@
      * Starts the management agent in the target VM
      */
     private static void startManagementAgent(String pid) throws IOException {
-        /*
-         * JAR file normally in ${java.home}/jre/lib but may be in ${java.home}/lib
-         * with development/non-images builds
-         */
-        String home = System.getProperty("java.home");
-        String agent = home + File.separator + "jre" + File.separator + "lib"
-                + File.separator + "management-agent.jar";
-        File f = new File(agent);
-        if (!f.exists()) {
-            agent = home + File.separator + "lib" + File.separator +
-                "management-agent.jar";
-            f = new File(agent);
-            if (!f.exists()) {
-                throw new RuntimeException("management-agent.jar missing");
-            }
-        }
-        agent = f.getCanonicalPath();
-
-        System.out.println("Loading " + agent + " into target VM ...");
-
         try {
-            VirtualMachine.attach(pid).loadAgent(agent);
+            VirtualMachine.attach(pid).startLocalManagementAgent();
         } catch (Exception x) {
             throw new IOException(x.getMessage());
         }
@@ -122,8 +101,7 @@
 
         if (agentPropLocalConnectorAddress == null &&
             jvmstatLocalConnectorAddress == null) {
-            // No JMX Connector address so attach to VM, and load
-            // management-agent.jar
+            // No JMX Connector address so attach to VM, and start local agent
             startManagementAgent(pid);
             agentPropLocalConnectorAddress = (String)
                 vm.getAgentProperties().get(LOCAL_CONNECTOR_ADDRESS_PROP);
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Tue Jun 10 11:15:23 2014 +0100
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Wed Jun 11 15:47:53 2014 +0200
@@ -31,16 +31,13 @@
 import java.rmi.registry.Registry;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 
 import javax.management.*;
@@ -60,7 +57,6 @@
  *          JCMD achieves the desired results
  */
 public class JMXStartStopTest {
-    private static final String TEST_JDK = System.getProperty("test.jdk");
     private static final String TEST_SRC = System.getProperty("test.src");
 
     private static final boolean verbose = false;
@@ -117,8 +113,8 @@
                                   QueryExp query)
     throws Exception {
 
-        Set names = server.queryNames(pattern,query);
-        for (Iterator i=names.iterator(); i.hasNext(); ) {
+        Set<ObjectName> names = server.queryNames(pattern,query);
+        for (Iterator<ObjectName> i = names.iterator(); i.hasNext(); ) {
             ObjectName name = (ObjectName)i.next();
             MBeanInfo info = server.getMBeanInfo(name);
             dbg_print("Got MBean: " + name);
@@ -128,7 +124,7 @@
                 continue;
             for (MBeanAttributeInfo attr : attrs) {
                 if (attr.isReadable()) {
-                    Object o = server.getAttribute(name, attr.getName());
+                    server.getAttribute(name, attr.getName());
                 }
             }
         }
@@ -149,9 +145,8 @@
             }
 
             JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
-            Map m = new HashMap();
 
-            JMXConnector c = JMXConnectorFactory.connect(url,m);
+            JMXConnector c = JMXConnectorFactory.connect(url, null);
 
             MBeanServerConnection conn = c.getMBeanServerConnection();
             ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
@@ -221,9 +216,8 @@
                 port);
 
         JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
-        Map m = new HashMap();
 
-        JMXConnector c = JMXConnectorFactory.connect(url,m);
+        JMXConnector c = JMXConnectorFactory.connect(url, null);
 
         MBeanServerConnection conn = c.getMBeanServerConnection();
         ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
@@ -314,25 +308,6 @@
         }
     }
 
-    /**
-     * Retrieves the PID of the test application using JCMD
-     * @return The PID of the test application
-     * @throws InterruptedException
-     * @throws IOException
-     */
-    private static String getPID() throws InterruptedException, IOException {
-        final AtomicReference<String> pid = new AtomicReference<>();
-        jcmd(
-            null,
-            line -> {
-                if (line.endsWith("JMXStartStopDoSomething")) {
-                    pid.set(line.split(" ")[0]);
-                }
-            }
-        );
-        return pid.get();
-    }
-
     private static class Something {
         private Process p;
         private final ProcessBuilder pb;
@@ -473,7 +448,7 @@
     private static final String CMD_START= "ManagementAgent.start";
     private static final String CMD_START_LOCAL = "ManagementAgent.start_local";
 
-    private static void test_01() throws Exception {
+    static void test_01() throws Exception {
         // Run an app with JMX enabled stop it and
         // restart on other port
 
@@ -499,7 +474,7 @@
         }
     }
 
-    private static void test_02() throws Exception {
+    static void test_02() throws Exception {
         // Run an app without JMX enabled
         // start JMX by jcmd
 
@@ -520,7 +495,7 @@
         }
     }
 
-    private static void test_03() throws Exception {
+    static void test_03() throws Exception {
         // Run an app without JMX enabled
         // start JMX by jcmd on one port than on other one
 
@@ -550,7 +525,7 @@
         }
     }
 
-    private static void test_04() throws Exception {
+    static void test_04() throws Exception {
         // Run an app without JMX enabled
         // start JMX by jcmd on one port, specify rmi port explicitly
 
@@ -571,7 +546,7 @@
         }
     }
 
-    private static void test_05() throws Exception {
+    static void test_05() throws Exception {
         // Run an app without JMX enabled, it will enable local server
         // but should leave remote server disabled
 
@@ -589,7 +564,7 @@
         }
     }
 
-    private static void test_06() throws Exception {
+    static void test_06() throws Exception {
         // Run an app without JMX enabled
         // start JMX by jcmd on one port, specify rmi port explicitly
         // attempt to start it again
@@ -636,38 +611,39 @@
             jcmd(CMD_STOP);
             jcmd(CMD_STOP);
 
-            ServerSocket ss = new ServerSocket(0);
+            try (ServerSocket ss = new ServerSocket(0))
+            {
+                jcmd(
+                    line -> {
+                        if (line.contains("Port already in use: " + ss.getLocalPort())) {
+                            checks[2] = true;
+                        }
+                    },
+                    CMD_START,
+                    "jmxremote.port=" + ss.getLocalPort(),
+                    "jmxremote.rmi.port=" + pa.getPort2(),
+                    "jmxremote.authenticate=false",
+                    "jmxremote.ssl=false");
 
-            jcmd(
-                line -> {
-                    if (line.contains("Port already in use: " + ss.getLocalPort())) {
-                        checks[2] = true;
-                    }
-                },
-                CMD_START,
-                "jmxremote.port=" + ss.getLocalPort(),
-                "jmxremote.rmi.port=" + pa.getPort2(),
-                "jmxremote.authenticate=false",
-                "jmxremote.ssl=false");
-
-            if (!checks[0]) {
-                throw new Exception("Starting agent on port " + pa.getPort1() + " should " +
-                                    "report an invalid agent state");
-            }
-            if (!checks[1]) {
-                throw new Exception("Starting agent on poprt " + pa.getPort2() + " should " +
-                                    "report an invalid agent state");
-            }
-            if (!checks[2]) {
-                throw new Exception("Starting agent on port " + ss.getLocalPort() + " should " +
-                                    "report port in use");
+                if (!checks[0]) {
+                    throw new Exception("Starting agent on port " + pa.getPort1() + " should " +
+                                        "report an invalid agent state");
+                }
+                if (!checks[1]) {
+                    throw new Exception("Starting agent on poprt " + pa.getPort2() + " should " +
+                                        "report an invalid agent state");
+                }
+                if (!checks[2]) {
+                    throw new Exception("Starting agent on port " + ss.getLocalPort() + " should " +
+                                        "report port in use");
+                }
             }
         } finally {
             s.stop();
         }
     }
 
-    private static void test_07() throws Exception {
+    static void test_07() throws Exception {
         // Run an app without JMX enabled, but with some properties set
         // in command line.
         // make sure these properties overridden corectly
@@ -694,7 +670,7 @@
         }
     }
 
-    private static void test_08() throws Exception {
+    static void test_08() throws Exception {
         // Run an app with JMX enabled and with some properties set
         // in command line.
         // stop JMX agent and then start it again with different property values
@@ -729,7 +705,7 @@
         }
     }
 
-    private static void test_09() throws Exception {
+    static void test_09() throws Exception {
         // Run an app with JMX enabled and with some properties set
         // in command line.
         // stop JMX agent and then start it again with different property values
@@ -766,7 +742,7 @@
         }
     }
 
-    private static void test_10() throws Exception {
+    static void test_10() throws Exception {
         // Run an app with JMX enabled and with some properties set
         // in command line.
         // stop JMX agent and then start it again with different property values
@@ -803,7 +779,7 @@
         }
     }
 
-    private static void test_11() throws Exception {
+    static void test_11() throws Exception {
         // Run an app with JMX enabled
         // stop remote agent
         // make sure local agent is not affected
@@ -825,7 +801,7 @@
         }
     }
 
-    private static void test_12() throws Exception {
+    static void test_12() throws Exception {
         // Run an app with JMX disabled
         // start local agent only
 
@@ -845,28 +821,4 @@
         }
     }
 
-    private static void test_13() throws Exception {
-        // Run an app with -javaagent make sure it works as expected -
-        // system properties are ignored
-
-        System.out.println("**** Test thirteen ****");
-        PortAllocator pa = new PortAllocator();
-
-        String agent = TEST_JDK + "/jre/lib/management-agent.jar";
-        if (!new File(agent).exists()) {
-            agent = TEST_JDK + "/lib/management-agent.jar";
-        }
-
-        Something s = doSomething("test_14",
-            "-javaagent:" + agent + "=com.sun.management.jmxremote.port=" +
-                pa.getPort1() + ",com.sun.management.jmxremote.authenticate=false",
-            "-Dcom.sun.management.jmxremote.ssl=false"
-        );
-
-        try {
-            testNoConnect(pa.port1);
-        } finally {
-            s.stop();
-        }
-    }
 }