Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/management/Agent.java
38827 views
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 sun.management;
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.InvocationTargetException;
35
import java.lang.reflect.Method;
36
import java.net.InetAddress;
37
import java.net.UnknownHostException;
38
import java.text.MessageFormat;
39
import java.util.MissingResourceException;
40
import java.util.Properties;
41
import java.util.ResourceBundle;
42
43
import javax.management.remote.JMXConnectorServer;
44
import javax.management.remote.JMXServiceURL;
45
46
import static sun.management.AgentConfigurationError.*;
47
import sun.management.jmxremote.ConnectorBootstrap;
48
import sun.management.jdp.JdpController;
49
import sun.management.jdp.JdpException;
50
import sun.misc.VMSupport;
51
52
/**
53
* This Agent is started by the VM when -Dcom.sun.management.snmp or
54
* -Dcom.sun.management.jmxremote is set. This class will be loaded by the
55
* system class loader. Also jmx framework could be started by jcmd
56
*/
57
public class Agent {
58
// management properties
59
60
private static Properties mgmtProps;
61
private static ResourceBundle messageRB;
62
private static final String CONFIG_FILE =
63
"com.sun.management.config.file";
64
private static final String SNMP_PORT =
65
"com.sun.management.snmp.port";
66
private static final String JMXREMOTE =
67
"com.sun.management.jmxremote";
68
private static final String JMXREMOTE_PORT =
69
"com.sun.management.jmxremote.port";
70
private static final String RMI_PORT =
71
"com.sun.management.jmxremote.rmi.port";
72
private static final String ENABLE_THREAD_CONTENTION_MONITORING =
73
"com.sun.management.enableThreadContentionMonitoring";
74
private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
75
"com.sun.management.jmxremote.localConnectorAddress";
76
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
77
"sun.management.snmp.AdaptorBootstrap";
78
79
private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
80
private static final int JDP_DEFAULT_PORT = 7095;
81
82
// The only active agent allowed
83
private static JMXConnectorServer jmxServer = null;
84
85
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
86
// and return property set if args is null or empty
87
// return empty property set
88
private static Properties parseString(String args) {
89
Properties argProps = new Properties();
90
if (args != null && !args.trim().equals("")) {
91
for (String option : args.split(",")) {
92
String s[] = option.split("=", 2);
93
String name = s[0].trim();
94
String value = (s.length > 1) ? s[1].trim() : "";
95
96
if (!name.startsWith("com.sun.management.")) {
97
error(INVALID_OPTION, name);
98
}
99
100
argProps.setProperty(name, value);
101
}
102
}
103
104
return argProps;
105
}
106
107
// invoked by -javaagent or -Dcom.sun.management.agent.class
108
public static void premain(String args) throws Exception {
109
agentmain(args);
110
}
111
112
// invoked by attach mechanism
113
public static void agentmain(String args) throws Exception {
114
if (args == null || args.length() == 0) {
115
args = JMXREMOTE; // default to local management
116
}
117
118
Properties arg_props = parseString(args);
119
120
// Read properties from the config file
121
Properties config_props = new Properties();
122
String fname = arg_props.getProperty(CONFIG_FILE);
123
readConfiguration(fname, config_props);
124
125
// Arguments override config file
126
config_props.putAll(arg_props);
127
startAgent(config_props);
128
}
129
130
// jcmd ManagementAgent.start_local entry point
131
// Also called due to command-line via startAgent()
132
private static synchronized void startLocalManagementAgent() {
133
Properties agentProps = VMSupport.getAgentProperties();
134
135
// start local connector if not started
136
if (agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP) == null) {
137
JMXConnectorServer cs = ConnectorBootstrap.startLocalConnectorServer();
138
String address = cs.getAddress().toString();
139
// Add the local connector address to the agent properties
140
agentProps.put(LOCAL_CONNECTOR_ADDRESS_PROP, address);
141
142
try {
143
// export the address to the instrumentation buffer
144
ConnectorAddressLink.export(address);
145
} catch (Exception x) {
146
// Connector server started but unable to export address
147
// to instrumentation buffer - non-fatal error.
148
warning(EXPORT_ADDRESS_FAILED, x.getMessage());
149
}
150
}
151
}
152
153
// jcmd ManagementAgent.start entry point
154
// This method starts the remote JMX agent and starts neither
155
// the local JMX agent nor the SNMP agent
156
// @see #startLocalManagementAgent and also @see #startAgent.
157
private static synchronized void startRemoteManagementAgent(String args) throws Exception {
158
if (jmxServer != null) {
159
throw new RuntimeException(getText(INVALID_STATE, "Agent already started"));
160
}
161
162
try {
163
Properties argProps = parseString(args);
164
Properties configProps = new Properties();
165
166
// Load the management properties from the config file
167
// if config file is not specified readConfiguration implicitly
168
// reads <java.home>/lib/management/management.properties
169
170
String fname = System.getProperty(CONFIG_FILE);
171
readConfiguration(fname, configProps);
172
173
// management properties can be overridden by system properties
174
// which take precedence
175
Properties sysProps = System.getProperties();
176
synchronized (sysProps) {
177
configProps.putAll(sysProps);
178
}
179
180
// if user specifies config file into command line for either
181
// jcmd utilities or attach command it overrides properties set in
182
// command line at the time of VM start
183
String fnameUser = argProps.getProperty(CONFIG_FILE);
184
if (fnameUser != null) {
185
readConfiguration(fnameUser, configProps);
186
}
187
188
// arguments specified in command line of jcmd utilities
189
// override both system properties and one set by config file
190
// specified in jcmd command line
191
configProps.putAll(argProps);
192
193
// jcmd doesn't allow to change ThreadContentionMonitoring, but user
194
// can specify this property inside config file, so enable optional
195
// monitoring functionality if this property is set
196
final String enableThreadContentionMonitoring =
197
configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
198
199
if (enableThreadContentionMonitoring != null) {
200
ManagementFactory.getThreadMXBean().
201
setThreadContentionMonitoringEnabled(true);
202
}
203
204
String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT);
205
if (jmxremotePort != null) {
206
jmxServer = ConnectorBootstrap.
207
startRemoteConnectorServer(jmxremotePort, configProps);
208
209
startDiscoveryService(configProps);
210
} else {
211
throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, "No port specified");
212
}
213
} catch (AgentConfigurationError err) {
214
error(err);
215
}
216
}
217
218
private static synchronized void stopRemoteManagementAgent() throws Exception {
219
220
JdpController.stopDiscoveryService();
221
222
if (jmxServer != null) {
223
ConnectorBootstrap.unexportRegistry();
224
225
// Attempt to stop already stopped agent
226
// Don't cause any errors.
227
jmxServer.stop();
228
jmxServer = null;
229
}
230
}
231
232
private static void startAgent(Properties props) throws Exception {
233
String snmpPort = props.getProperty(SNMP_PORT);
234
String jmxremote = props.getProperty(JMXREMOTE);
235
String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
236
237
// Enable optional monitoring functionality if requested
238
final String enableThreadContentionMonitoring =
239
props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
240
if (enableThreadContentionMonitoring != null) {
241
ManagementFactory.getThreadMXBean().
242
setThreadContentionMonitoringEnabled(true);
243
}
244
245
try {
246
if (snmpPort != null) {
247
loadSnmpAgent(snmpPort, props);
248
}
249
250
/*
251
* If the jmxremote.port property is set then we start the
252
* RMIConnectorServer for remote M&M.
253
*
254
* If the jmxremote or jmxremote.port properties are set then
255
* we start a RMIConnectorServer for local M&M. The address
256
* of this "local" server is exported as a counter to the jstat
257
* instrumentation buffer.
258
*/
259
if (jmxremote != null || jmxremotePort != null) {
260
if (jmxremotePort != null) {
261
jmxServer = ConnectorBootstrap.
262
startRemoteConnectorServer(jmxremotePort, props);
263
startDiscoveryService(props);
264
}
265
startLocalManagementAgent();
266
}
267
268
} catch (AgentConfigurationError e) {
269
error(e);
270
} catch (Exception e) {
271
error(e);
272
}
273
}
274
275
private static void startDiscoveryService(Properties props)
276
throws IOException {
277
// Start discovery service if requested
278
String discoveryPort = props.getProperty("com.sun.management.jdp.port");
279
String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
280
String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery");
281
282
// Decide whether we should start autodicovery service.
283
// To start autodiscovery following conditions should be met:
284
// autodiscovery==true OR (autodicovery==null AND jdp.port != NULL)
285
286
boolean shouldStart = false;
287
if (discoveryShouldStart == null){
288
shouldStart = (discoveryPort != null);
289
}
290
else{
291
try{
292
shouldStart = Boolean.parseBoolean(discoveryShouldStart);
293
} catch (NumberFormatException e) {
294
throw new AgentConfigurationError("Couldn't parse autodiscovery argument");
295
}
296
}
297
298
if (shouldStart) {
299
// port and address are required arguments and have no default values
300
InetAddress address;
301
try {
302
address = (discoveryAddress == null) ?
303
InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
304
} catch (UnknownHostException e) {
305
throw new AgentConfigurationError("Unable to broadcast to requested address", e);
306
}
307
308
int port = JDP_DEFAULT_PORT;
309
if (discoveryPort != null) {
310
try {
311
port = Integer.parseInt(discoveryPort);
312
} catch (NumberFormatException e) {
313
throw new AgentConfigurationError("Couldn't parse JDP port argument");
314
}
315
}
316
317
// Rebuilding service URL to broadcast it
318
String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
319
String rmiPort = props.getProperty(RMI_PORT);
320
321
JMXServiceURL url = jmxServer.getAddress();
322
String hostname = url.getHost();
323
324
String jmxUrlStr = (rmiPort != null)
325
? String.format(
326
"service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi",
327
hostname, rmiPort, hostname, jmxremotePort)
328
: String.format(
329
"service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort);
330
331
String instanceName = props.getProperty("com.sun.management.jdp.name");
332
333
try{
334
JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
335
}
336
catch(JdpException e){
337
throw new AgentConfigurationError("Couldn't start JDP service", e);
338
}
339
}
340
}
341
342
public static Properties loadManagementProperties() {
343
Properties props = new Properties();
344
345
// Load the management properties from the config file
346
347
String fname = System.getProperty(CONFIG_FILE);
348
readConfiguration(fname, props);
349
350
// management properties can be overridden by system properties
351
// which take precedence
352
Properties sysProps = System.getProperties();
353
synchronized (sysProps) {
354
props.putAll(sysProps);
355
}
356
357
return props;
358
}
359
360
public static synchronized Properties getManagementProperties() {
361
if (mgmtProps == null) {
362
String configFile = System.getProperty(CONFIG_FILE);
363
String snmpPort = System.getProperty(SNMP_PORT);
364
String jmxremote = System.getProperty(JMXREMOTE);
365
String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
366
367
if (configFile == null && snmpPort == null
368
&& jmxremote == null && jmxremotePort == null) {
369
// return if out-of-the-management option is not specified
370
return null;
371
}
372
mgmtProps = loadManagementProperties();
373
}
374
return mgmtProps;
375
}
376
377
private static void loadSnmpAgent(String snmpPort, Properties props) {
378
try {
379
// invoke the following through reflection:
380
// AdaptorBootstrap.initialize(snmpPort, props);
381
final Class<?> adaptorClass =
382
Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null);
383
final Method initializeMethod =
384
adaptorClass.getMethod("initialize",
385
String.class, Properties.class);
386
initializeMethod.invoke(null, snmpPort, props);
387
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) {
388
// snmp runtime doesn't exist - initialization fails
389
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x);
390
} catch (InvocationTargetException x) {
391
final Throwable cause = x.getCause();
392
if (cause instanceof RuntimeException) {
393
throw (RuntimeException) cause;
394
} else if (cause instanceof Error) {
395
throw (Error) cause;
396
}
397
// should not happen...
398
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause);
399
}
400
}
401
402
// read config file and initialize the properties
403
private static void readConfiguration(String fname, Properties p) {
404
if (fname == null) {
405
String home = System.getProperty("java.home");
406
if (home == null) {
407
throw new Error("Can't find java.home ??");
408
}
409
StringBuffer defaultFileName = new StringBuffer(home);
410
defaultFileName.append(File.separator).append("lib");
411
defaultFileName.append(File.separator).append("management");
412
defaultFileName.append(File.separator).append("management.properties");
413
// Set file name
414
fname = defaultFileName.toString();
415
}
416
final File configFile = new File(fname);
417
if (!configFile.exists()) {
418
error(CONFIG_FILE_NOT_FOUND, fname);
419
}
420
421
InputStream in = null;
422
try {
423
in = new FileInputStream(configFile);
424
BufferedInputStream bin = new BufferedInputStream(in);
425
p.load(bin);
426
} catch (FileNotFoundException e) {
427
error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
428
} catch (IOException e) {
429
error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
430
} catch (SecurityException e) {
431
error(CONFIG_FILE_ACCESS_DENIED, fname);
432
} finally {
433
if (in != null) {
434
try {
435
in.close();
436
} catch (IOException e) {
437
error(CONFIG_FILE_CLOSE_FAILED, fname);
438
}
439
}
440
}
441
}
442
443
public static void startAgent() throws Exception {
444
String prop = System.getProperty("com.sun.management.agent.class");
445
446
// -Dcom.sun.management.agent.class not set so read management
447
// properties and start agent
448
if (prop == null) {
449
// initialize management properties
450
Properties props = getManagementProperties();
451
if (props != null) {
452
startAgent(props);
453
}
454
return;
455
}
456
457
// -Dcom.sun.management.agent.class=<agent classname>:<agent args>
458
String[] values = prop.split(":");
459
if (values.length < 1 || values.length > 2) {
460
error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
461
}
462
String cname = values[0];
463
String args = (values.length == 2 ? values[1] : null);
464
465
if (cname == null || cname.length() == 0) {
466
error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
467
}
468
469
if (cname != null) {
470
try {
471
// Instantiate the named class.
472
// invoke the premain(String args) method
473
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
474
Method premain = clz.getMethod("premain",
475
new Class<?>[]{String.class});
476
premain.invoke(null, /* static */
477
new Object[]{args});
478
} catch (ClassNotFoundException ex) {
479
error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
480
} catch (NoSuchMethodException ex) {
481
error(AGENT_CLASS_PREMAIN_NOT_FOUND, "\"" + cname + "\"");
482
} catch (SecurityException ex) {
483
error(AGENT_CLASS_ACCESS_DENIED);
484
} catch (Exception ex) {
485
String msg = (ex.getCause() == null
486
? ex.getMessage()
487
: ex.getCause().getMessage());
488
error(AGENT_CLASS_FAILED, msg);
489
}
490
}
491
}
492
493
public static void error(String key) {
494
String keyText = getText(key);
495
System.err.print(getText("agent.err.error") + ": " + keyText);
496
throw new RuntimeException(keyText);
497
}
498
499
public static void error(String key, String message) {
500
String keyText = getText(key);
501
System.err.print(getText("agent.err.error") + ": " + keyText);
502
System.err.println(": " + message);
503
throw new RuntimeException(keyText + ": " + message);
504
}
505
506
public static void error(Exception e) {
507
e.printStackTrace();
508
System.err.println(getText(AGENT_EXCEPTION) + ": " + e.toString());
509
throw new RuntimeException(e);
510
}
511
512
public static void error(AgentConfigurationError e) {
513
String keyText = getText(e.getError());
514
String[] params = e.getParams();
515
516
System.err.print(getText("agent.err.error") + ": " + keyText);
517
518
if (params != null && params.length != 0) {
519
StringBuffer message = new StringBuffer(params[0]);
520
for (int i = 1; i < params.length; i++) {
521
message.append(" " + params[i]);
522
}
523
System.err.println(": " + message);
524
}
525
e.printStackTrace();
526
throw new RuntimeException(e);
527
}
528
529
public static void warning(String key, String message) {
530
System.err.print(getText("agent.err.warning") + ": " + getText(key));
531
System.err.println(": " + message);
532
}
533
534
private static void initResource() {
535
try {
536
messageRB =
537
ResourceBundle.getBundle("sun.management.resources.agent");
538
} catch (MissingResourceException e) {
539
throw new Error("Fatal: Resource for management agent is missing");
540
}
541
}
542
543
public static String getText(String key) {
544
if (messageRB == null) {
545
initResource();
546
}
547
try {
548
return messageRB.getString(key);
549
} catch (MissingResourceException e) {
550
return "Missing management agent resource bundle: key = \"" + key + "\"";
551
}
552
}
553
554
public static String getText(String key, String... args) {
555
if (messageRB == null) {
556
initResource();
557
}
558
String format = messageRB.getString(key);
559
if (format == null) {
560
format = "missing resource key: key = \"" + key + "\", "
561
+ "arguments = \"{0}\", \"{1}\", \"{2}\"";
562
}
563
return MessageFormat.format(format, (Object[]) args);
564
}
565
}
566
567