--- a/jdk/src/share/classes/sun/management/Agent.java Sun Feb 26 17:25:42 2012 +0000
+++ b/jdk/src/share/classes/sun/management/Agent.java Mon Feb 27 15:21:18 2012 +0400
@@ -1,5 +1,5 @@
/*
- * 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 static sun.management.AgentConfigurationError.*;
import sun.management.jmxremote.ConnectorBootstrap;
-import static sun.management.AgentConfigurationError.*;
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 @@
"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 @@
args = JMXREMOTE; // default to local management
}
- // Parse agent options into properties
+ Properties arg_props = parseString(args);
+
+ // 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);
+ }
- 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) {
+ // jcmd ManagementAgent.start_local entry point
+ // Also called due to command-line via startAgent()
+ private static synchronized void startLocalManagementAgent(){
+ Properties agentProps = VMSupport.getAgentProperties();
- // 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);
- }
- }
- }
+ // 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
+
+ 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 override config file
- config_props.putAll(arg_props);
- startAgent(config_props);
+ // 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 @@
try {
if (snmpPort != null) {
- loadSnmpAgent(snmpPort, props);
+ loadSnmpAgent(snmpPort, props);
}
/*
@@ -142,31 +239,14 @@
* 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 @@
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);