mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-20 20:00:28 +00:00
8044135: Add API to start JMX agent from attach framework
Reviewed-by: alanb
This commit is contained in:
parent
66135672e1
commit
855f7c421e
@ -76,16 +76,10 @@ import java.io.IOException;
|
||||
* // 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 @@ import java.io.IOException;
|
||||
* </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>
|
||||
*
|
||||
@ -610,6 +604,68 @@ public abstract class VirtualMachine {
|
||||
*/
|
||||
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
|
||||
|
||||
@ -33,7 +33,7 @@ import com.sun.tools.attach.spi.AttachProvider;
|
||||
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 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
|
||||
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
|
||||
|
||||
@ -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 @@ import java.io.File;
|
||||
// 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 @@ public class LocalVirtualMachine {
|
||||
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();
|
||||
|
||||
@ -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 @@ class SimpleVirtualMachine extends VirtualMachine {
|
||||
|
||||
public void dataDumpRequest() throws IOException {
|
||||
}
|
||||
|
||||
public String startLocalManagementAgent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void startManagementAgent(Properties agentProperties) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
211
jdk/test/com/sun/tools/attach/StartManagementAgent.java
Normal file
211
jdk/test/com/sun/tools/attach/StartManagementAgent.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 @@ public class JvmstatCountersTest {
|
||||
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) {
|
||||
|
||||
@ -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 java.util.concurrent.atomic.AtomicReference;
|
||||
*/
|
||||
|
||||
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 @@ public class LocalManagementTest {
|
||||
}
|
||||
}
|
||||
|
||||
@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 @@ public class LocalManagementTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 java.lang.management.RuntimeMXBean;
|
||||
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 @@ public class TestManager {
|
||||
* 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 @@ public class TestManager {
|
||||
|
||||
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);
|
||||
|
||||
@ -31,16 +31,13 @@ import java.rmi.registry.LocateRegistry;
|
||||
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 @@ import jdk.testlibrary.JDKToolLauncher;
|
||||
* 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 @@ public class JMXStartStopTest {
|
||||
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 @@ public class JMXStartStopTest {
|
||||
continue;
|
||||
for (MBeanAttributeInfo attr : attrs) {
|
||||
if (attr.isReadable()) {
|
||||
Object o = server.getAttribute(name, attr.getName());
|
||||
server.getAttribute(name, attr.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,9 +145,8 @@ public class JMXStartStopTest {
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public class JMXStartStopTest {
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class JMXStartStopTest {
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user