提交 11722be3 编写于 作者: D dsamersoff

7110104: It should be possible to stop and start JMX Agent at runtime

Summary: Added a capability to start and stop JMX Agent by jcmd
Reviewed-by: acorn, mchung
上级 41510c72
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -25,30 +25,34 @@
package sun.management;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.management.ManagementFactory;
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import javax.management.remote.JMXConnectorServer;
import sun.management.jmxremote.ConnectorBootstrap;
import static sun.management.AgentConfigurationError.*;
import sun.management.jmxremote.ConnectorBootstrap;
import sun.misc.VMSupport;
/**
* This Agent is started by the VM when -Dcom.sun.management.snmp
* or -Dcom.sun.management.jmxremote is set. This class will be
* loaded by the system class loader.
* loaded by the system class loader. Also jmx framework could
* be started by jcmd
*/
public class Agent {
// management properties
......@@ -69,7 +73,33 @@ public class Agent {
"com.sun.management.jmxremote.localConnectorAddress";
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
"sun.management.snmp.AdaptorBootstrap";
"sun.management.snmp.AdaptorBootstrap";
// The only active agent allowed
private static JMXConnectorServer jmxServer = null;
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
// and return property set if args is null or empty
// return empty property set
private static Properties parseString(String args){
Properties argProps = new Properties();
if (args != null) {
for (String option : args.split(",")) {
String s[] = option.split("=", 2);
String name = s[0].trim();
String value = (s.length > 1) ? s[1].trim() : "";
if (!name.startsWith("com.sun.management.")) {
error(INVALID_OPTION, name);
}
argProps.setProperty(name, value);
}
}
return argProps;
}
// invoked by -javaagent or -Dcom.sun.management.agent.class
public static void premain(String args) throws Exception {
......@@ -82,37 +112,104 @@ public class Agent {
args = JMXREMOTE; // default to local management
}
// Parse agent options into properties
Properties arg_props = parseString(args);
Properties arg_props = new Properties();
if (args != null) {
String[] options = args.split(",");
for (int i=0; i<options.length; i++) {
String[] option = options[i].split("=");
if (option.length >= 1 && option.length <= 2) {
String name = option[0];
String value = (option.length == 1) ? "" : option[1];
if (name != null && name.length() > 0) {
// Assume that any com.sun.management.* options are okay
if (name.startsWith("com.sun.management.")) {
arg_props.setProperty(name, value);
} else {
error(INVALID_OPTION, name);
}
}
}
// Read properties from the config file
Properties config_props = new Properties();
String fname = arg_props.getProperty(CONFIG_FILE);
readConfiguration(fname, config_props);
// Arguments override config file
config_props.putAll(arg_props);
startAgent(config_props);
}
// jcmd ManagementAgent.start_local entry point
// Also called due to command-line via startAgent()
private static synchronized void startLocalManagementAgent(){
Properties agentProps = VMSupport.getAgentProperties();
// start local connector if not started
if (agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP) == null) {
JMXConnectorServer cs = ConnectorBootstrap.startLocalConnectorServer();
String address = cs.getAddress().toString();
// Add the local connector address to the agent properties
agentProps.put(LOCAL_CONNECTOR_ADDRESS_PROP, address);
try {
// export the address to the instrumentation buffer
ConnectorAddressLink.export(address);
} catch (Exception x) {
// Connector server started but unable to export address
// to instrumentation buffer - non-fatal error.
warning(EXPORT_ADDRESS_FAILED, x.getMessage());
}
}
}
// Read properties from the config file
Properties config_props = new Properties();
String fname = arg_props.getProperty(CONFIG_FILE);
readConfiguration(fname, config_props);
// jcmd ManagementAgent.start entry point
// This method starts the remote JMX agent and starts neither
// the local JMX agent nor the SNMP agent
// @see #startLocalManagementAgent and also @see #startAgent.
private static synchronized void startRemoteManagementAgent(String args) throws Exception {
if (jmxServer != null) {
throw new RuntimeException(getText(INVALID_STATE, "Agent already started"));
}
Properties argProps = parseString(args);
Properties configProps = new Properties();
// Load the management properties from the config file
// if config file is not specified readConfiguration implicitly
// reads <java.home>/lib/management/management.properties
// Arguments override config file
config_props.putAll(arg_props);
startAgent(config_props);
String fname = System.getProperty(CONFIG_FILE);
readConfiguration(fname, configProps);
// management properties can be overridden by system properties
// which take precedence
configProps.putAll(System.getProperties());
// if user specifies config file into command line for either
// jcmd utilities or attach command it overrides properties set in
// command line at the time of VM start
String fnameUser = argProps.getProperty(CONFIG_FILE);
if (fnameUser != null) {
readConfiguration(fnameUser, configProps);
}
// arguments specified in command line of jcmd utilities
// override both system properties and one set by config file
// specified in jcmd command line
configProps.putAll(argProps);
// jcmd doesn't allow to change ThreadContentionMonitoring, but user
// can specify this property inside config file, so enable optional
// monitoring functionality if this property is set
final String enableThreadContentionMonitoring =
configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
if (enableThreadContentionMonitoring != null) {
ManagementFactory.getThreadMXBean().
setThreadContentionMonitoringEnabled(true);
}
String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT);
if (jmxremotePort != null) {
jmxServer = ConnectorBootstrap.
startRemoteConnectorServer(jmxremotePort, configProps);
}
}
private static synchronized void stopRemoteManagementAgent() throws Exception {
if (jmxServer != null) {
ConnectorBootstrap.unexportRegistry();
// Attempt to stop already stopped agent
// Don't cause any errors.
jmxServer.stop();
jmxServer = null;
}
}
private static void startAgent(Properties props) throws Exception {
......@@ -130,7 +227,7 @@ public class Agent {
try {
if (snmpPort != null) {
loadSnmpAgent(snmpPort, props);
loadSnmpAgent(snmpPort, props);
}
/*
......@@ -142,31 +239,14 @@ public class Agent {
* of this "local" server is exported as a counter to the jstat
* instrumentation buffer.
*/
if (jmxremote != null || jmxremotePort != null) {
if (jmxremote != null || jmxremotePort != null) {
if (jmxremotePort != null) {
ConnectorBootstrap.initialize(jmxremotePort, props);
jmxServer = ConnectorBootstrap.
startRemoteConnectorServer(jmxremotePort, props);
}
startLocalManagementAgent();
}
Properties agentProps = VMSupport.getAgentProperties();
// start local connector if not started
// System.out.println("local address : " +
// agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP));
if (agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP) == null) {
JMXConnectorServer cs = ConnectorBootstrap.startLocalConnectorServer();
String address = cs.getAddress().toString();
// Add the local connector address to the agent properties
agentProps.put(LOCAL_CONNECTOR_ADDRESS_PROP, address);
try {
// export the address to the instrumentation buffer
ConnectorAddressLink.export(address);
} catch (Exception x) {
// Connector server started but unable to export address
// to instrumentation buffer - non-fatal error.
warning(EXPORT_ADDRESS_FAILED, x.getMessage());
}
}
}
} catch (AgentConfigurationError e) {
error(e.getError(), e.getParams());
} catch (Exception e) {
......@@ -187,9 +267,9 @@ public class Agent {
props.putAll(System.getProperties());
return props;
}
}
public static synchronized Properties getManagementProperties() {
public static synchronized Properties getManagementProperties() {
if (mgmtProps == null) {
String configFile = System.getProperty(CONFIG_FILE);
String snmpPort = System.getProperty(SNMP_PORT);
......
/*
* Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2012, 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
......@@ -53,6 +53,8 @@ public class AgentConfigurationError extends Error {
"agent.err.invalid.agentclass";
public static final String INVALID_JMXREMOTE_PORT =
"agent.err.invalid.jmxremote.port";
public static final String INVALID_JMXREMOTE_RMI_PORT =
"agent.err.invalid.jmxremote.rmi.port";
public static final String PASSWORD_FILE_NOT_SET =
"agent.err.password.file.notset";
public static final String PASSWORD_FILE_NOT_READABLE =
......@@ -105,6 +107,8 @@ public class AgentConfigurationError extends Error {
"agent.err.snmp.adaptor.start.failed";
public static final String SNMP_MIB_INIT_FAILED =
"agent.err.snmp.mib.init.failed";
public static final String INVALID_STATE =
"agent.err.invalid.state";
private final String error;
private final String[] params;
......
/*
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -28,25 +28,22 @@ package sun.management.jmxremote;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.RemoteObject;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.RemoteObject;
import java.rmi.server.UnicastRemoteObject;
import java.security.KeyStore;
import java.security.Principal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
......@@ -55,35 +52,31 @@ import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.lang.management.ManagementFactory;
import javax.net.ssl.*;
import javax.management.MBeanServer;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
import javax.security.auth.Subject;
import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
import com.sun.jmx.remote.internal.RMIExporter;
import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
import com.sun.jmx.remote.util.ClassLogger;
import sun.management.Agent;
import sun.management.AgentConfigurationError;
import static sun.management.AgentConfigurationError.*;
import sun.management.ConnectorAddressLink;
import sun.management.FileSystem;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.internal.RMIExporter;
import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
/**
* This class initializes and starts the RMIConnectorServer for JSR 163
......@@ -114,6 +107,8 @@ public final class ConnectorBootstrap {
public static final String PORT =
"com.sun.management.jmxremote.port";
public static final String RMI_PORT =
"com.sun.management.jmxremote.rmi.port";
public static final String CONFIG_FILE_NAME =
"com.sun.management.config.file";
public static final String USE_LOCAL_ONLY =
......@@ -266,34 +261,61 @@ public final class ConnectorBootstrap {
private final String accessFile;
}
/**
* Initializes and starts the JMX Connector Server.
* If the com.sun.management.jmxremote.port property is not defined,
* simply return. Otherwise, attempts to load the config file, and
* then calls {@link #initialize(java.lang.String, java.util.Properties)}.
*
**/
public static synchronized JMXConnectorServer initialize() {
// The variable below is here to support stop functionality
// It would be overriten if you call startRemoteCommectionServer second
// time. It's OK for now as logic in Agent.java forbids mutiple agents
private static Registry registry = null;
// Load a new management properties
final Properties props = Agent.loadManagementProperties();
if (props == null) {
return null;
public static void unexportRegistry() {
// Remove the entry from registry
try {
if (registry != null) {
UnicastRemoteObject.unexportObject(registry, true);
registry = null;
}
} catch(NoSuchObjectException ex) {
// This exception can appears only if we attempt
// to unexportRegistry second time. So it's safe
// to ignore it without additional messages.
}
}
final String portStr = props.getProperty(PropertyNames.PORT);
/**
* Initializes and starts the JMX Connector Server.
* If the com.sun.management.jmxremote.port property is not defined,
* simply return. Otherwise, attempts to load the config file, and
* then calls {@link #startRemoteConnectorServer
* (java.lang.String, java.util.Properties)}.
*
* This method is used by some jtreg tests.
**/
public static synchronized JMXConnectorServer initialize() {
// Load a new management properties
final Properties props = Agent.loadManagementProperties();
if (props == null) {
return null;
}
final String portStr = props.getProperty(PropertyNames.PORT);
return startRemoteConnectorServer(portStr, props);
}
// System.out.println("initializing: {port=" + portStr + ",
// properties="+props+"}");
return initialize(portStr, props);
/**
* This method is used by some jtreg tests.
*
* @see #startRemoteConnectorServer
* (String portStr, Properties props)
*/
public static synchronized JMXConnectorServer initialize(String portStr, Properties props) {
return startRemoteConnectorServer(portStr, props);
}
/**
* Initializes and starts a JMX Connector Server for remote
* monitoring and management.
**/
public static synchronized JMXConnectorServer initialize(String portStr, Properties props) {
public static synchronized JMXConnectorServer startRemoteConnectorServer(String portStr, Properties props) {
// Get port number
final int port;
......@@ -306,6 +328,22 @@ public final class ConnectorBootstrap {
throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, portStr);
}
// User can specify a port to be used to export rmi object,
// in order to simplify firewall rules
// if port is not specified random one will be allocated.
int rmiPort = 0;
String rmiPortStr = props.getProperty(PropertyNames.RMI_PORT);
try {
if (rmiPortStr != null) {
rmiPort = Integer.parseInt(rmiPortStr);
}
} catch (NumberFormatException x) {
throw new AgentConfigurationError(INVALID_JMXREMOTE_RMI_PORT, x, rmiPortStr);
}
if (rmiPort < 0) {
throw new AgentConfigurationError(INVALID_JMXREMOTE_RMI_PORT, rmiPortStr);
}
// Do we use authentication?
final String useAuthenticationStr =
props.getProperty(PropertyNames.USE_AUTHENTICATION,
......@@ -387,9 +425,10 @@ public final class ConnectorBootstrap {
}
if (log.debugOn()) {
log.debug("initialize",
Agent.getText("jmxremote.ConnectorBootstrap.initialize") +
log.debug("startRemoteConnectorServer",
Agent.getText("jmxremote.ConnectorBootstrap.starting") +
"\n\t" + PropertyNames.PORT + "=" + port +
"\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
"\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
"\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
"\n\t" + PropertyNames.SSL_CONFIG_FILE_NAME + "=" + sslConfigFileName +
......@@ -404,7 +443,7 @@ public final class ConnectorBootstrap {
(useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" +
passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" +
loginConfigName)) : "\n\t" +
Agent.getText("jmxremote.ConnectorBootstrap.initialize.noAuthentication")) +
Agent.getText("jmxremote.ConnectorBootstrap.noAuthentication")) +
(useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" +
accessFileName) : "") +
"");
......@@ -415,15 +454,15 @@ public final class ConnectorBootstrap {
JMXServiceURL url = null;
try {
final JMXConnectorServerData data = exportMBeanServer(
mbs, port, useSsl, useRegistrySsl,
mbs, port, rmiPort, useSsl, useRegistrySsl,
sslConfigFileName, enabledCipherSuitesList,
enabledProtocolsList, sslNeedClientAuth,
useAuthentication, loginConfigName,
passwordFileName, accessFileName);
cs = data.jmxConnectorServer;
url = data.jmxRemoteURL;
log.config("initialize",
Agent.getText("jmxremote.ConnectorBootstrap.initialize.ready",
log.config("startRemoteConnectorServer",
Agent.getText("jmxremote.ConnectorBootstrap.ready",
url.toString()));
} catch (Exception e) {
throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
......@@ -442,7 +481,7 @@ public final class ConnectorBootstrap {
// Remote connector server started but unable to export remote
// connector address and associated configuration properties to
// the instrumentation buffer - non-fatal error.
log.debug("initialize", e);
log.debug("startRemoteConnectorServer", e);
}
return cs;
}
......@@ -517,9 +556,9 @@ public final class ConnectorBootstrap {
try {
if (fs.supportsFileSecurity(file)) {
if (!fs.isAccessUserOnly(file)) {
final String msg = Agent.getText("jmxremote.ConnectorBootstrap.initialize.password.readonly",
final String msg = Agent.getText("jmxremote.ConnectorBootstrap.password.readonly",
passwordFileName);
log.config("initialize", msg);
log.config("startRemoteConnectorServer", msg);
throw new AgentConfigurationError(PASSWORD_FILE_ACCESS_NOT_RESTRICTED,
passwordFileName);
}
......@@ -560,9 +599,9 @@ public final class ConnectorBootstrap {
if (fs.supportsFileSecurity(file)) {
if (!fs.isAccessUserOnly(file)) {
final String msg = Agent.getText(
"jmxremote.ConnectorBootstrap.initialize.file.readonly",
"jmxremote.ConnectorBootstrap.file.readonly",
restrictedFileName);
log.config("initialize", msg);
log.config("startRemoteConnectorServer", msg);
throw new AgentConfigurationError(
FILE_ACCESS_NOT_RESTRICTED, restrictedFileName);
}
......@@ -662,6 +701,7 @@ public final class ConnectorBootstrap {
private static JMXConnectorServerData exportMBeanServer(
MBeanServer mbs,
int port,
int rmiPort,
boolean useSsl,
boolean useRegistrySsl,
String sslConfigFileName,
......@@ -679,7 +719,7 @@ public final class ConnectorBootstrap {
* IDs. */
System.setProperty("java.rmi.server.randomIDs", "true");
JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
JMXServiceURL url = new JMXServiceURL("rmi", null, rmiPort);
Map<String, Object> env = new HashMap<>();
......@@ -736,7 +776,6 @@ public final class ConnectorBootstrap {
}
}
final Registry registry;
if (useRegistrySsl) {
registry =
new SingleEntryRegistry(port, csf, ssf,
......@@ -747,10 +786,12 @@ public final class ConnectorBootstrap {
"jmxrmi", exporter.firstExported);
}
JMXServiceURL remoteURL = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://" + url.getHost() + ":" +
((UnicastRef) ((RemoteObject) registry).getRef()).getLiveRef().getPort() +
"/jmxrmi");
int registryPort =
((UnicastRef) ((RemoteObject) registry).getRef()).getLiveRef().getPort();
String jmxUrlStr = String.format("service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi",
url.getHost(), registryPort);
JMXServiceURL remoteURL = new JMXServiceURL(jmxUrlStr);
/* Our exporter remembers the first object it was asked to
export, which will be an RMIServerImpl appropriate for
......
#
#
# Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2004, 2012, 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
......@@ -43,8 +43,9 @@ agent.err.agentclass.failed = Management agent class failed
agent.err.premain.notfound = premain(String) does not exist in agent class
agent.err.agentclass.access.denied = Access to premain(String) is denied
agent.err.invalid.agentclass = Invalid com.sun.management.agent.class property value
agent.err.invalid.state = Invalid agent state
agent.err.invalid.jmxremote.port = Invalid com.sun.management.jmxremote.port number
agent.err.invalid.jmxremote.rmi.port = Invalid com.sun.management.jmxremote.rmi.port number
agent.err.file.not.set = File not specified
agent.err.file.not.readable = File not readable
......@@ -78,11 +79,11 @@ agent.err.acl.file.access.notrestricted = Password file read access must be rest
agent.err.snmp.adaptor.start.failed = Failed to start SNMP adaptor with address
agent.err.snmp.mib.init.failed = Failed to initialize SNMP MIB with error
jmxremote.ConnectorBootstrap.initialize = Starting JMX Connector Server:
jmxremote.ConnectorBootstrap.initialize.noAuthentication = No Authentication
jmxremote.ConnectorBootstrap.initialize.ready = JMX Connector ready at: {0}
jmxremote.ConnectorBootstrap.initialize.password.readonly = Password file read access must be restricted: {0}
jmxremote.ConnectorBootstrap.initialize.file.readonly = File read access must be restricted: {0}
jmxremote.ConnectorBootstrap.starting = Starting JMX Connector Server:
jmxremote.ConnectorBootstrap.noAuthentication = No Authentication
jmxremote.ConnectorBootstrap.ready = JMX Connector ready at: {0}
jmxremote.ConnectorBootstrap.password.readonly = Password file read access must be restricted: {0}
jmxremote.ConnectorBootstrap.file.readonly = File read access must be restricted: {0}
jmxremote.AdaptorBootstrap.getTargetList.processing = Processing ACL
jmxremote.AdaptorBootstrap.getTargetList.adding = Adding target: {0}
......
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2012, 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
......@@ -35,10 +35,10 @@ public class AgentCheckTest {
public static void main(String[] args){
String [][] testStrings = {
{"agent.err.error", "", ""},
{"jmxremote.ConnectorBootstrap.initialize", "", ""},
{"jmxremote.ConnectorBootstrap.initialize.noAuthentication", "", ""},
{"jmxremote.ConnectorBootstrap.initialize.ready", "Phony JMXServiceURL", ""},
{"jmxremote.ConnectorBootstrap.initialize.password.readonly", "Phony passwordFileName", ""},
{"jmxremote.ConnectorBootstrap.starting", "", ""},
{"jmxremote.ConnectorBootstrap.noAuthentication", "", ""},
{"jmxremote.ConnectorBootstrap.ready", "Phony JMXServiceURL", ""},
{"jmxremote.ConnectorBootstrap.password.readonly", "Phony passwordFileName", ""},
{"jmxremote.AdaptorBootstrap.getTargetList.processing", "", ""},
{"jmxremote.AdaptorBootstrap.getTargetList.adding", "Phony target", ""},
{"jmxremote.AdaptorBootstrap.getTargetList.starting", "", ""},
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.RandomAccessFile;
public class JMXStartStopDoSomething {
public void doSomething(){
try {
for (int i=0; i < 10; ++i) {
RandomAccessFile f = new RandomAccessFile("/dev/null","r");
int n = f.read();
f.close();
}
} catch (Throwable e) {
System.err.println("Something bad happens:" +e);
}
}
public static void main(String args[]) throws Exception {
System.err.println("main enter");
int count = 1;
while(count > 0) {
JMXStartStopDoSomething p = new JMXStartStopDoSomething();
p.doSomething();
Thread.sleep(1);
}
// System.err.println("main exit");
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.management.*;
import javax.management.remote.*;
import sun.management.AgentConfigurationError;
import sun.management.jmxremote.ConnectorBootstrap;
public class JMXStartStopTest {
static boolean verbose = false;
static void dbg_print(String msg){
if (verbose) {
System.err.println("DBG: " +msg);
}
}
static void dbg_print(String msg, Throwable ex){
if (verbose) {
System.err.println("DBG: " + msg + " " + ex.getMessage() );
ex.printStackTrace(System.err);
}
}
public static int listMBeans(MBeanServerConnection server, ObjectName pattern, QueryExp query)
throws Exception {
Set names = server.queryNames(pattern,query);
for (Iterator i=names.iterator(); i.hasNext(); ) {
ObjectName name = (ObjectName)i.next();
MBeanInfo info = server.getMBeanInfo(name);
dbg_print("Got MBean: " + name);
MBeanAttributeInfo[] attrs = info.getAttributes();
if (attrs == null)
continue;
for (int j=0; j<attrs.length; j++) {
if (attrs[j].isReadable()) {
Object o = server.getAttribute(name,attrs[j].getName());
}
}
}
return names.size();
}
public void run_local(String strPid)
throws Exception {
String jmxUrlStr = null;
int pid = Integer.parseInt(strPid);
try {
jmxUrlStr = sun.management.ConnectorAddressLink.importFrom(pid);
dbg_print("Local Service URL: " +jmxUrlStr);
if ( jmxUrlStr == null ) {
throw new Exception("No Service URL. Local agent not started?");
}
JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
Map m = new HashMap();
JMXConnector c = JMXConnectorFactory.connect(url,m);
MBeanServerConnection conn = c.getMBeanServerConnection();
ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
int count = listMBeans(conn,pattern,null);
if (count == 0)
throw new Exception("Expected at least one matching "+ "MBean for "+pattern);
} catch (IOException e) {
dbg_print("Cannot find process : " + pid);
throw e;
}
}
public void run(String args[]) throws Exception {
dbg_print("RmiRegistry lookup...");
int port = 4567;
if (args != null && args.length > 0) {
port = Integer.parseInt(args[0]);
}
dbg_print("Using port: " + port);
int rmiPort = 0;
if (args != null && args.length > 1) {
rmiPort = Integer.parseInt(args[1]);
}
dbg_print("Using rmi port: " + rmiPort);
Registry registry = LocateRegistry.getRegistry(port);
// "jmxrmi"
String[] relist = registry.list();
for (int i = 0; i < relist.length; ++i) {
dbg_print("Got registry: " + relist[i]);
}
String jmxUrlStr = (rmiPort != 0) ?
String.format("service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi", rmiPort, port) :
String.format("service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi",port);
JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
Map m = new HashMap();
JMXConnector c = JMXConnectorFactory.connect(url,m);
MBeanServerConnection conn = c.getMBeanServerConnection();
ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
int count = listMBeans(conn,pattern,null);
if (count == 0)
throw new Exception("Expected at least one matching "+ "MBean for "+pattern);
}
public static void main(String args[]) {
JMXStartStopTest manager = new JMXStartStopTest();
try {
if (args!=null && args[0].equals("local")) {
manager.run_local(args[1]);
} else {
manager.run(args);
}
} catch (RuntimeException r) {
dbg_print("No connection: ", r);
System.out.println("NO_CONN");
System.exit(1);
} catch (Throwable t) {
dbg_print("No connection: ", t);
System.out.println("NO_CONN");
System.exit(2);
}
System.out.println("OK_CONN");
System.exit(0);
}
}
#!/bin/sh
# Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
# @test
# @bug 7110104
# @build JMXStartStopTest JMXStartStopDoSomething
# @run shell JMXStartStopTest.sh --jtreg --no-compile
# @summary No word Failed expected in the test output
_verbose=no
_server=no
_jtreg=no
_compile=yes
_testsuite="01,02,03,04,05,06,07,08,09,10,11,12,13"
_port_one=50234
_port_two=50235
_testclasses=".classes"
_testsrc=`pwd`
_logname=".classes/JMXStartStopTest_output.txt"
_compile(){
if [ ! -e ${_testclasses} ]
then
mkdir -p ${_testclasses}
fi
rm -f ${_testclasses}/JMXStartStopTest.class
# Compile testcase
${TESTJAVA}/bin/javac -d ${_testclasses} JMXStartStopDoSomething.java JMXStartStopTest.java
if [ ! -e ${_testclasses}/JMXStartStopTest.class ]
then
echo "ERROR: Can't compile"
exit -1
fi
}
_app_start(){
if [ "${_verbose}" = "yes" ]
then
echo "RUN: ${TESTJAVA}/bin/java -server $* -cp ${_testclasses} JMXStartStopDoSomething "
fi
${TESTJAVA}/bin/java -server $* -cp ${_testclasses} JMXStartStopDoSomething >> ${_logname} 2>&1 &
sleep 1
pid=`_get_pid`
if [ "x${pid}" = "x" ]
then
echo "ERROR: Test app not started"
exit -1
fi
}
_get_pid(){
${TESTJAVA}/bin/jps | sed -n "/JMXStartStopDoSomething/s/ .*//p"
}
_app_stop(){
pid=`_get_pid`
if [ "x${pid}" != "x" ]
then
kill $pid
fi
# Stop on first failed test under jtreg
if [ "x$1" = "xFailed" -a "${_jtreg}" = "yes" ]
then
exit -1
fi
}
testme(){
${TESTJAVA}/bin/java -cp ${_testclasses} JMXStartStopTest $*
}
_jcmd(){
if [ "${_verbose}" = "yes" ]
then
echo "RUN: ${TESTJAVA}/bin/jcmd JMXStartStopDoSomething $*"
${TESTJAVA}/bin/jcmd JMXStartStopDoSomething $*
else
${TESTJAVA}/bin/jcmd JMXStartStopDoSomething $* > /dev/null 2>/dev/null
fi
}
_echo(){
echo "$*"
echo "$*" >> ${_logname}
}
# ============= TESTS ======================================
test_01(){
# Run an app with JMX enabled stop it and
# restart on other port
_echo "**** Test one ****"
_app_start -Dcom.sun.management.jmxremote.port=$1 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
res1=`testme $1`
_jcmd ManagementAgent.stop
res2=`testme $1`
_jcmd ManagementAgent.start jmxremote.port=$2
res3=`testme $2`
if [ "${res1}" = "OK_CONN" -a "${res2}" = "NO_CONN" -a "${res3}" = "OK_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(OK):${res1} r2(NO):${res2} r3(OK):${res3}"
_app_stop "Failed"
fi
_app_stop
}
test_02(){
# Run an app without JMX enabled
# start JMX by jcmd
_echo "**** Test two ****"
_app_start
_jcmd ManagementAgent.start jmxremote.port=$1 jmxremote.authenticate=false jmxremote.ssl=false
res1=`testme $1`
if [ "${res1}" = "OK_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(OK):${res1}"
_app_stop "Failed"
fi
_app_stop
}
test_03(){
# Run an app without JMX enabled
# start JMX by jcmd on one port than on other one
_echo "**** Test three ****"
_app_start
_jcmd ManagementAgent.start jmxremote.port=$1 jmxremote.authenticate=false jmxremote.ssl=false
# Second agent shouldn't start
_jcmd ManagementAgent.start jmxremote.port=$2 jmxremote.authenticate=false jmxremote.ssl=false
# First agent should connect
res1=`testme $1`
if [ "${res1}" = "OK_CONN" ]
then
_echo "Passed $1"
else
_echo "Failed r1(NO):${res1}"
_app_stop "Failed"
fi
#Second agent shouldn't connect
res1=`testme $2`
if [ "${res1}" = "NO_CONN" ]
then
_echo "Passed $2"
else
_echo "Failed r1(OK):${res1}"
fi
_app_stop
}
test_04(){
# Run an app without JMX enabled
# start JMX by jcmd on one port, specify rmi port explicitly
_echo "**** Test four ****"
_app_start
_jcmd ManagementAgent.start jmxremote.port=$1 jmxremote.rmi.port=$2 jmxremote.authenticate=false jmxremote.ssl=false
# First agent should connect
res1=`testme $1 $2`
if [ "${res1}" = "OK_CONN" ]
then
_echo "Passed $1 $2"
else
_echo "Failed r1(NO):${res1}"
_app_stop "Failed"
fi
_app_stop
}
test_05(){
# Run an app without JMX enabled, it will enable local server
# but should leave remote server disabled
_echo "**** Test five ****"
_app_start
_jcmd ManagementAgent.start jmxremote=1
# First agent should connect
res1=`testme $1`
if [ "${res1}" = "NO_CONN" ]
then
_echo "Passed $1 $2"
else
_echo "Failed r1(OK):${res1}"
_app_stop "Failed"
fi
_app_stop
}
test_06(){
# Run an app without JMX enabled
# start JMX by jcmd on one port, specify rmi port explicitly
# attempt to start it again
# 1) with the same port
# 2) with other port
# 3) attempt to stop it twice
# Check for valid messages in the output
_echo "**** Test six ****"
_app_start
_jcmd ManagementAgent.start jmxremote.port=$1 jmxremote.authenticate=false jmxremote.ssl=false
# First agent should connect
res1=`testme $1 $2`
if [ "${res1}" = "OK_CONN" ]
then
_echo "Passed $1 $2"
else
_echo "Failed r1(NO):${res1}"
_app_stop "Failed"
fi
_jcmd ManagementAgent.start jmxremote.port=$1 jmxremote.authenticate=false jmxremote.ssl=false
_jcmd ManagementAgent.start jmxremote.port=$2 jmxremote.authenticate=false jmxremote.ssl=false
_jcmd ManagementAgent.stop
_jcmd ManagementAgent.stop
_jcmd ManagementAgent.start jmxremote.port=22 jmxremote.rmi.port=$2 jmxremote.authenticate=false jmxremote.ssl=false
_app_stop
}
test_07(){
# Run an app without JMX enabled, but with some properties set
# in command line.
# make sure these properties overriden corectly
_echo "**** Test seven ****"
_app_start -Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=true
res1=`testme $1`
_jcmd ManagementAgent.start jmxremote.port=$2 jmxremote.authenticate=false jmxremote.ssl=false
res2=`testme $2`
if [ "${res1}" = "NO_CONN" -a "${res2}" = "OK_CONN" ]
then
echo "Passed"
else
_echo "Failed r1(NO):${res1} r2(OK):${res2}"
_app_stop "Failed"
fi
_app_stop
}
test_08(){
# 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
# make sure these properties overriden corectly
_echo "**** Test eight ****"
_app_start -Dcom.sun.management.jmxremote.port=$1 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=true
res1=`testme $1`
_jcmd ManagementAgent.stop
res2=`testme $1`
_jcmd ManagementAgent.start jmxremote.port=$2 jmxremote.authenticate=false jmxremote.ssl=false
res3=`testme $2`
if [ "${res1}" = "NO_CONN" -a "${res2}" = "NO_CONN" -a "${res3}" = "OK_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(NO):${res1} r2(NO):${res2} r3(OK):${res3}"
_app_stop "Failed"
fi
_app_stop
}
test_09(){
# 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
# specifing some property in management config file and some of them
# in command line
# make sure these properties overriden corectly
_echo "**** Test nine ****"
_app_start -Dcom.sun.management.config.file=${_testsrc}/management_cl.properties \
-Dcom.sun.management.jmxremote.authenticate=false
res1=`testme $1`
_jcmd ManagementAgent.stop
res2=`testme $1`
_jcmd ManagementAgent.start config.file=${_testsrc}/management_jcmd.properties \
jmxremote.authenticate=false jmxremote.port=$2
res3=`testme $2`
if [ "${res1}" = "NO_CONN" -a "${res2}" = "NO_CONN" -a "${res3}" = "OK_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(NO):${res1} r2(NO):${res2} r3(OK):${res3}"
_app_stop "Failed"
fi
_app_stop
}
test_10(){
# 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
# stop JMX agent again and then start it without property value
# make sure these properties overriden corectly
_echo "**** Test ten ****"
_app_start -Dcom.sun.management.jmxremote.port=$1 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=true
res1=`testme $1`
_jcmd ManagementAgent.stop
_jcmd ManagementAgent.start jmxremote.ssl=false jmxremote.port=$1
res2=`testme $1`
_jcmd ManagementAgent.stop
_jcmd ManagementAgent.start jmxremote.port=$1
res3=`testme $1`
if [ "${res1}" = "NO_CONN" -a "${res2}" = "OK_CONN" -a "${res3}" = "NO_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(NO):${res1} r2(OK):${res2} r3(NO):${res3}"
_app_stop "Failed"
fi
_app_stop
}
test_11(){
# Run an app with JMX enabled
# stop remote agent
# make sure local agent is not affected
_echo "**** Test eleven ****"
_app_start -Dcom.sun.management.jmxremote.port=$2 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
res1=`testme $2`
_jcmd ManagementAgent.stop
pid=`${TESTJAVA}/bin/jps | sed -n "/JMXStartStopDoSomething/s/ .*//p"`
res2=`testme local ${pid}`
if [ "${res1}" = "OK_CONN" -a "${res2}" = "OK_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(OK):${res1} r2(OK):${res2}"
_app_stop "Failed"
fi
_app_stop
}
test_12(){
# Run an app with JMX disabled
# start local agent only
_echo "**** Test twelve ****"
_app_start
res1=`testme $1`
_jcmd ManagementAgent.start_local
pid=`_get_pid`
if [ "x${pid}" = "x" ]
then
res2="NO_CONN"
else
res2=`testme local ${pid}`
fi
if [ "${res1}" = "NO_CONN" -a "${res2}" = "OK_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(NO):${res1} r2(OK):${res2}"
_app_stop "Failed"
fi
_app_stop
}
test_13(){
# Run an app with -javaagent make sure it works as expected - system properties are ignored
_echo "**** Test 13 ****"
AGENT="${TESTJAVA}/jre/lib/management-agent.jar"
if [ ! -f ${AGENT} ]
then
AGENT="${TESTJAVA}/lib/management-agent.jar"
fi
_app_start -javaagent:${AGENT}=com.sun.management.jmxremote.port=$1,com.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
res1=`testme $1`
if [ "${res1}" = "NO_CONN" ]
then
_echo "Passed"
else
_echo "Failed r1(NO):${res1}"
_app_stop "Failed"
fi
_app_stop
}
#============== Server tests =======================
server_test_01(){
_echo "**** Server test one ****"
_app_start -Dcom.sun.management.jmxremote.port=$1 \
-Dcom.sun.management.jmxremote.rmi.port=$2 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
}
# ============= MAIN =======================================
if [ "x${TESTJAVA}" = "x" ]
then
echo "TESTJAVA env have to be set"
exit
fi
if [ ! -x "${TESTJAVA}/bin/jcmd" ]
then
echo "${TESTJAVA}/bin/jcmd"
echo "Doesn't exist or not an executable"
if [ "${_verbose}" != "yes" ]
then
exit
fi
fi
#------------------------------------------------------------------------------
# reading parameters
for parm in "$@"
do
case $parm in
--verbose) _verbose=yes ;;
--server) _server=yes ;;
--jtreg) _jtreg=yes ;;
--no-compile) _compile=no ;;
--testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
--port-one=*) _port_one=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
--port-two=*) _port_two=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
*)
echo "Undefined parameter $parm. Try --help for help"
exit
;;
esac
done
if [ ${_compile} = "yes" ]
then
_compile
fi
if [ ${_jtreg} = "yes" ]
then
_testclasses=${TESTCLASSES}
_testsrc=${TESTSRC}
_logname="JMXStartStopTest_output.txt"
fi
rm -f ${_logname}
# Start server mode tests
# All of them require manual cleanup
if [ "x${_server}" = "xyes" ]
then
server_test_01 ${_port_one} ${_port_two}
else
# Local mode tests
for i in `echo ${_testsuite} | sed -e "s/,/ /g"`
do
test_${i} ${_port_one} ${_port_two}
done
fi
1. Setup two hosts
2. Make sure tcp connection between them works
3. run tcpdump -i <interface> host <host2_name> and 'tcp[13] & 2!=0'
on host 1
4. run JMXStartStopTest.sh --server on host2
5. run jconsole on host1
6. connect jconsole to host2:50234
Make sure jconsole works
Make sure only host2.50234 and host2.50235 appears in tcpdump output.
com.sun.management.jmxremote.ssl=true
com.sun.management.internal.read_from_config_file_cl=true
com.sun.management.jmxremote.ssl=false
jmxremote.authenticate=true
com.sun.management.internal.read_from_config_file_jcmd=true
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册