1 /*
2 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.agent;
26
27 import java.io.BufferedInputStream;
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.lang.management.ManagementFactory;
34 import java.lang.reflect.Method;
35 import java.net.InetAddress;
36 import java.net.MalformedURLException;
37 import java.net.UnknownHostException;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.text.MessageFormat;
41 import java.util.HashMap;
42 import java.util.Map;
43 import java.util.MissingResourceException;
44 import java.util.Properties;
45 import java.util.ResourceBundle;
46 import java.util.ServiceLoader;
47 import java.util.function.Function;
48 import java.util.function.Predicate;
49
50 import javax.management.remote.JMXConnectorServer;
51 import javax.management.remote.JMXServiceURL;
52
53 import static jdk.internal.agent.AgentConfigurationError.*;
54 import jdk.internal.agent.spi.AgentProvider;
55 import jdk.internal.vm.VMSupport;
56 import sun.management.jdp.JdpController;
57 import sun.management.jdp.JdpException;
58 import sun.management.jmxremote.ConnectorBootstrap;
59
60 /**
61 * This Agent is started by the VM when -Dcom.sun.management.snmp or
62 * -Dcom.sun.management.jmxremote is set. This class will be loaded by the
63 * system class loader. Also jmx framework could be started by jcmd
64 */
65 public class Agent {
66 /**
67 * Agent status collector strategy class
68 */
69 private static abstract class StatusCollector {
70 protected static final Map<String, String> DEFAULT_PROPS = new HashMap<>();
71
72 static {
73 DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PORT,
74 ConnectorBootstrap.DefaultValues.PORT);
75 DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY,
245 "com.sun.management.jmxremote";
246 private static final String JMXREMOTE_PORT =
247 "com.sun.management.jmxremote.port";
248 private static final String RMI_PORT =
249 "com.sun.management.jmxremote.rmi.port";
250 private static final String ENABLE_THREAD_CONTENTION_MONITORING =
251 "com.sun.management.enableThreadContentionMonitoring";
252 private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
253 "com.sun.management.jmxremote.localConnectorAddress";
254 private static final String SNMP_AGENT_NAME =
255 "SnmpAgent";
256
257 private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
258 private static final int JDP_DEFAULT_PORT = 7095;
259
260 // The only active agent allowed
261 private static JMXConnectorServer jmxServer = null;
262 // The properties used to configure the server
263 private static Properties configProps = null;
264
265 // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
266 // and return property set if args is null or empty
267 // return empty property set
268 private static Properties parseString(String args) {
269 Properties argProps = new Properties();
270 if (args != null && !args.trim().equals("")) {
271 for (String option : args.split(",")) {
272 String s[] = option.split("=", 2);
273 String name = s[0].trim();
274 String value = (s.length > 1) ? s[1].trim() : "";
275
276 if (!name.startsWith("com.sun.management.")) {
277 error(INVALID_OPTION, name);
278 }
279
280 argProps.setProperty(name, value);
281 }
282 }
283
284 return argProps;
285 }
286
287 // invoked by -javaagent or -Dcom.sun.management.agent.class
288 public static void premain(String args) throws Exception {
592 in = new FileInputStream(configFile);
593 BufferedInputStream bin = new BufferedInputStream(in);
594 p.load(bin);
595 } catch (FileNotFoundException e) {
596 error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
597 } catch (IOException e) {
598 error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
599 } catch (SecurityException e) {
600 error(CONFIG_FILE_ACCESS_DENIED, fname);
601 } finally {
602 if (in != null) {
603 try {
604 in.close();
605 } catch (IOException e) {
606 error(CONFIG_FILE_CLOSE_FAILED, fname);
607 }
608 }
609 }
610 }
611
612 public static void startAgent() throws Exception {
613 String prop = System.getProperty("com.sun.management.agent.class");
614
615 // -Dcom.sun.management.agent.class not set so read management
616 // properties and start agent
617 if (prop == null) {
618 // initialize management properties
619 Properties props = getManagementProperties();
620 if (props != null) {
621 startAgent(props);
622 }
623 return;
624 }
625
626 // -Dcom.sun.management.agent.class=<agent classname>:<agent args>
627 String[] values = prop.split(":");
628 if (values.length < 1 || values.length > 2) {
629 error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
630 }
631 String cname = values[0];
632 String args = (values.length == 2 ? values[1] : null);
633
634 if (cname == null || cname.length() == 0) {
635 error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
636 }
637
|
1 /*
2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.agent;
26
27 import java.io.BufferedInputStream;
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.lang.management.ManagementFactory;
34 import java.lang.reflect.Method;
35 import java.net.InetAddress;
36 import java.net.MalformedURLException;
37 import java.net.UnknownHostException;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.text.MessageFormat;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.LinkedHashMap;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.MissingResourceException;
47 import java.util.Optional;
48 import java.util.Properties;
49 import java.util.ResourceBundle;
50 import java.util.ServiceLoader;
51 import java.util.Set;
52 import java.util.function.Function;
53 import java.util.function.Predicate;
54
55 import javax.management.remote.JMXConnectorServer;
56 import javax.management.remote.JMXServiceURL;
57
58 import static jdk.internal.agent.AgentConfigurationError.*;
59 import jdk.internal.agent.spi.AgentProvider;
60 import jdk.internal.vm.VMSupport;
61 import sun.management.ManagementFactoryHelper;
62 import sun.management.VMManagement;
63 import sun.management.jdp.JdpController;
64 import sun.management.jdp.JdpException;
65 import sun.management.jmxremote.ConnectorBootstrap;
66
67 /**
68 * This Agent is started by the VM when -Dcom.sun.management.snmp or
69 * -Dcom.sun.management.jmxremote is set. This class will be loaded by the
70 * system class loader. Also jmx framework could be started by jcmd
71 */
72 public class Agent {
73 /**
74 * Agent status collector strategy class
75 */
76 private static abstract class StatusCollector {
77 protected static final Map<String, String> DEFAULT_PROPS = new HashMap<>();
78
79 static {
80 DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PORT,
81 ConnectorBootstrap.DefaultValues.PORT);
82 DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY,
252 "com.sun.management.jmxremote";
253 private static final String JMXREMOTE_PORT =
254 "com.sun.management.jmxremote.port";
255 private static final String RMI_PORT =
256 "com.sun.management.jmxremote.rmi.port";
257 private static final String ENABLE_THREAD_CONTENTION_MONITORING =
258 "com.sun.management.enableThreadContentionMonitoring";
259 private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
260 "com.sun.management.jmxremote.localConnectorAddress";
261 private static final String SNMP_AGENT_NAME =
262 "SnmpAgent";
263
264 private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
265 private static final int JDP_DEFAULT_PORT = 7095;
266
267 // The only active agent allowed
268 private static JMXConnectorServer jmxServer = null;
269 // The properties used to configure the server
270 private static Properties configProps = null;
271
272 private static final Map<String, String> XMANAGEMENTFLAS = Collections.unmodifiableMap(new LinkedHashMap<>() {{
273 put("config_file", "com.sun.management.config.file");
274 put("local", "com.sun.management.jmxremote");
275 put("port", "com.sun.management.jmxremote.port");
276 put("host", "com.sun.management.jmxremote.host");
277 put("rmiserver_port", "com.sun.management.jmxremote.rmi.port");
278 put("rmi_registry_ssl", "com.sun.management.jmxremote.registry.ssl");
279 put("ssl", "com.sun.management.jmxremote.ssl");
280 put("ssl_config_file", "com.sun.management.jmxremote.ssl.config.file");
281 put("ssl_client_auth", "com.sun.management.jmxremote.ssl.need.client.auth");
282 put("password_file", "com.sun.management.jmxremote.password.file");
283 put("authenticate", "com.sun.management.jmxremote.authenticate");
284 put("access_file", "com.sun.management.jmxremote.access.file");
285 }});
286
287 // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
288 // and return property set if args is null or empty
289 // return empty property set
290 private static Properties parseString(String args) {
291 if(args.startsWith("-Xmanagement")) {
292 return parseXmgmtArgs(args);
293 }
294 Properties argProps = new Properties();
295 if (args != null && !args.trim().equals("")) {
296 for (String option : args.split(",")) {
297 String s[] = option.split("=", 2);
298 String name = s[0].trim();
299 String value = (s.length > 1) ? s[1].trim() : "";
300
301 if (!name.startsWith("com.sun.management.")) {
302 error(INVALID_OPTION, name);
303 }
304
305 argProps.setProperty(name, value);
306 }
307 }
308
309 return argProps;
310 }
311
312 // invoked by -javaagent or -Dcom.sun.management.agent.class
313 public static void premain(String args) throws Exception {
617 in = new FileInputStream(configFile);
618 BufferedInputStream bin = new BufferedInputStream(in);
619 p.load(bin);
620 } catch (FileNotFoundException e) {
621 error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
622 } catch (IOException e) {
623 error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
624 } catch (SecurityException e) {
625 error(CONFIG_FILE_ACCESS_DENIED, fname);
626 } finally {
627 if (in != null) {
628 try {
629 in.close();
630 } catch (IOException e) {
631 error(CONFIG_FILE_CLOSE_FAILED, fname);
632 }
633 }
634 }
635 }
636
637 private static Properties parseXmgmtArgs(String args) {
638 Properties props = new Properties();
639 if(args != null && !args.trim().isEmpty()) {
640 args = args.trim();
641 if (args.equals("-Xmanagement") || args.equals("-Xmanagement:")) {
642 props.setProperty("com.sun.management.jmxremote", "true");
643 return props;
644 }
645
646 args = args.replaceFirst("^-Xmanagement:", "");
647 Set<String> keys = XMANAGEMENTFLAS.keySet();
648 for (String param : args.split(",")) {
649 String[] tokens = param.trim().split("=",2);
650 String name = tokens[0].trim();
651 if(keys.contains(name)) {
652 name = XMANAGEMENTFLAS.get(name);
653 String value = (tokens.length > 1) ? tokens[1].trim() : "";
654 props.setProperty(name, value);
655 } else {
656 error(INVALID_OPTION, name);
657 }
658 }
659 }
660 return props;
661 }
662
663
664 public static void startAgent() throws Exception {
665 String prop = System.getProperty("com.sun.management.agent.class");
666
667 // -Dcom.sun.management.agent.class not set so read management
668 // properties and start agent
669 if (prop == null) {
670 VMManagement vmManagement = ManagementFactoryHelper.getVMManagement();
671 if (vmManagement != null) {
672 List<String> vmArguments = vmManagement.getVmArguments();
673 Optional<String> argStr = vmArguments.stream().filter(a -> a.startsWith("-Xmanagement")).findFirst();
674 if (argStr.isPresent()) {
675 Properties props = parseXmgmtArgs(argStr.get());
676 props.forEach((a,b) -> System.setProperty((String) a,(String) b));
677 }
678 }
679 // initialize management properties
680 Properties props = getManagementProperties();
681 if (props != null) {
682 startAgent(props);
683 }
684 return;
685 }
686
687 // -Dcom.sun.management.agent.class=<agent classname>:<agent args>
688 String[] values = prop.split(":");
689 if (values.length < 1 || values.length > 2) {
690 error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
691 }
692 String cname = values[0];
693 String args = (values.length == 2 ? values[1] : null);
694
695 if (cname == null || cname.length() == 0) {
696 error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
697 }
698
|