提交 802f99a8 编写于 作者: F fparain

7150256: Add back Diagnostic Command JMX API

Reviewed-by: mchung, jbachorik
上级 ceeda996
#
# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2003, 2013, 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
......@@ -29,6 +29,7 @@
FILES_export = \
sun/management/ClassLoadingImpl.java \
sun/management/DiagnosticCommandImpl.java \
sun/management/FileSystemImpl.java \
sun/management/Flag.java \
sun/management/GarbageCollectorImpl.java \
......
#
# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2003, 2013, 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,6 +25,7 @@
FILES_c = \
ClassLoadingImpl.c \
DiagnosticCommandImpl.c \
FileSystemImpl.c \
Flag.c \
GarbageCollectorImpl.c \
......
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2005, 2013, 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
......@@ -39,6 +39,10 @@ SUNWprivate_1.1 {
Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
Java_com_sun_management_UnixOperatingSystem_initialize;
Java_sun_management_ClassLoadingImpl_setVerboseClass;
Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand;
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands;
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo;
Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled;
Java_sun_management_FileSystemImpl_isAccessUserOnly0;
Java_sun_management_Flag_getAllFlagNames;
Java_sun_management_Flag_getFlags;
......
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2005, 2013, 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
......@@ -39,6 +39,10 @@ SUNWprivate_1.1 {
Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
Java_com_sun_management_UnixOperatingSystem_initialize;
Java_sun_management_ClassLoadingImpl_setVerboseClass;
Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand;
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands;
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo;
Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled;
Java_sun_management_FileSystemImpl_isAccessUserOnly0;
Java_sun_management_Flag_getAllFlagNames;
Java_sun_management_Flag_getFlags;
......
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.management;
import java.lang.management.PlatformManagedObject;
import javax.management.DynamicMBean;
/**
* Management interface for the diagnostic commands for the HotSpot Virtual Machine.
*
* <p>The {code DiagnosticCommandMBean} is registered to the
* {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
* platform MBeanServer} as are other platform MBeans.
*
* <p>The {@link javax.management.ObjectName ObjectName} for uniquely identifying
* the diagnostic MBean within an MBeanServer is:
* <blockquote>
* {@code com.sun.management:type=DiagnosticCommand}
* </blockquote>
*
* <p>This MBean is a {@link javax.management.DynamicMBean DynamicMBean}
* and also a {@link javax.management.NotificationEmitter}.
* The {@code DiagnosticCommandMBean} is generated at runtime and is subject to
* modifications during the lifetime of the Java virtual machine.
*
* A <em>diagnostic command</em> is represented as an operation of
* the {@code DiagnosticCommandMBean} interface. Each diagnostic command has:
* <ul>
* <li>the diagnostic command name which is the name being referenced in
* the HotSpot Virtual Machine</li>
* <li>the MBean operation name which is the
* {@linkplain javax.management.MBeanOperationInfo#getName() name}
* generated for the diagnostic command operation invocation.
* The MBean operation name is implementation dependent</li>
* </ul>
*
* The recommended way to transform a diagnostic command name into a MBean
* operation name is as follows:
* <ul>
* <li>All characters from the first one to the first dot are set to be
* lower-case characters</li>
* <li>Every dot or underline character is removed and the following
* character is set to be an upper-case character</li>
* <li>All other characters are copied without modification</li>
* </ul>
*
* <p>The diagnostic command name is always provided with the meta-data on the
* operation in a field named {@code dcmd.name} (see below).
*
* <p>A diagnostic command may or may not support options or arguments.
* All the operations return {@code String} and either take
* no parameter for operations that do not support any option or argument,
* or take a {@code String[]} parameter for operations that support at least
* one option or argument.
* Each option or argument must be stored in a single String.
* Options or arguments split across several String instances are not supported.
*
* <p>The distinction between options and arguments: options are identified by
* the option name while arguments are identified by their position in the
* command line. Options and arguments are processed in the order of the array
* passed to the invocation method.
*
* <p>Like any operation of a dynamic MBean, each of these operations is
* described by {@link javax.management.MBeanOperationInfo MBeanOperationInfo}
* instance. Here's the values returned by this object:
* <ul>
* <li>{@link javax.management.MBeanOperationInfo#getName() getName()}
* returns the operation name generated from the diagnostic command name</li>
* <li>{@link javax.management.MBeanOperationInfo#getDescription() getDescription()}
* returns the diagnostic command description
* (the same as the one return in the 'help' command)</li>
* <li>{@link javax.management.MBeanOperationInfo#getImpact() getImpact()}
* returns <code>ACTION_INFO</code></li>
* <li>{@link javax.management.MBeanOperationInfo#getReturnType() getReturnType()}
* returns {@code java.lang.String}</li>
* <li>{@link javax.management.MBeanOperationInfo#getDescriptor() getDescriptor()}
* returns a Descriptor instance (see below)</li>
* </ul>
*
* <p>The {@link javax.management.Descriptor Descriptor}
* is a collection of fields containing additional
* meta-data for a JMX element. A field is a name and an associated value.
* The additional meta-data provided for an operation associated with a
* diagnostic command are described in the table below:
* <p>
*
* <table border="1" cellpadding="5">
* <tr>
* <th>Name</th><th>Type</th><th>Description</th>
* </tr>
* <tr>
* <td>dcmd.name</td><td>String</td>
* <td>The original diagnostic command name (not the operation name)</td>
* </tr>
* <tr>
* <td>dcmd.description</td><td>String</td>
* <td>The diagnostic command description</td>
* </tr>
* <tr>
* <td>dcmd.help</td><td>String</td>
* <td>The full help message for this diagnostic command (same output as
* the one produced by the 'help' command)</td>
* </tr>
* <tr>
* <td>dcmd.vmImpact</td><td>String</td>
* <td>The impact of the diagnostic command,
* this value is the same as the one printed in the 'impact'
* section of the help message of the diagnostic command, and it
* is different from the getImpact() of the MBeanOperationInfo</td>
* </tr>
* <tr>
* <td>dcmd.enabled</td><td>boolean</td>
* <td>True if the diagnostic command is enabled, false otherwise</td>
* </tr>
* <tr>
* <td>dcmd.permissionClass</td><td>String</td>
* <td>Some diagnostic command might require a specific permission to be
* executed, in addition to the MBeanPermission to invoke their
* associated MBean operation. This field returns the fully qualified
* name of the permission class or null if no permission is required
* </td>
* </tr>
* <tr>
* <td>dcmd.permissionName</td><td>String</td>
* <td>The fist argument of the permission required to execute this
* diagnostic command or null if no permission is required</td>
* </tr>
* <tr>
* <td>dcmd.permissionAction</td><td>String</td>
* <td>The second argument of the permission required to execute this
* diagnostic command or null if the permission constructor has only
* one argument (like the ManagementPermission) or if no permission
* is required</td>
* </tr>
* <tr>
* <td>dcmd.arguments</td><td>Descriptor</td>
* <td>A Descriptor instance containing the descriptions of options and
* arguments supported by the diagnostic command (see below)</td>
* </tr>
* </table>
* <p>
*
* <p>The description of parameters (options or arguments) of a diagnostic
* command is provided within a Descriptor instance. In this Descriptor,
* each field name is a parameter name, and each field value is itself
* a Descriptor instance. The fields provided in this second Descriptor
* instance are described in the table below:
*
* <table border="1" cellpadding="5">
* <tr>
* <th>Name</th><th>Type</th><th>Description</th>
* </tr>
* <tr>
* <td>dcmd.arg.name</td><td>String</td>
* <td>The name of the parameter</td>
* </tr>
* <tr>
* <td>dcmd.arg.type</td><td>String</td>
* <td>The type of the parameter. The returned String is the name of a type
* recognized by the diagnostic command parser. These types are not
* Java types and are implementation dependent.
* </td>
* </tr>
* <tr>
* <td>dcmd.arg.description</td><td>String</td>
* <td>The parameter description</td>
* </tr>
* <tr>
* <td>dcmd.arg.isMandatory</td><td>boolean</td>
* <td>True if the parameter is mandatory, false otherwise</td>
* </tr>
* <tr>
* <td>dcmd.arg.isOption</td><td>boolean</td>
* <td>True if the parameter is an option, false if it is an argument</td>
* </tr>
* <tr>
* <td>dcmd.arg.isMultiple</td><td>boolean</td>
* <td>True if the parameter can be specified several times, false
* otherwise</td>
* </tr>
* </table>
*
* <p>When the set of diagnostic commands currently supported by the Java
* Virtual Machine is modified, the {@code DiagnosticCommandMBean} emits
* a {@link javax.management.Notification} with a
* {@linkplain javax.management.Notification#getType() type} of
* <a href="{@docRoot}/../../../../api/javax/management/MBeanInfo.html#info-changed">
* {@code "jmx.mbean.info.changed"}</a> and a
* {@linkplain javax.management.Notification#getUserData() userData} that
* is the new {@code MBeanInfo}.
*
* @since 8
*/
public interface DiagnosticCommandMBean extends DynamicMBean
{
}
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -42,7 +42,9 @@ import javax.management.StandardMBean;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
......@@ -482,6 +484,11 @@ public class ManagementFactory {
}
}
}
HashMap<ObjectName, DynamicMBean> dynmbeans =
ManagementFactoryHelper.getPlatformDynamicMBeans();
for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {
addDynamicMBean(platformMBeanServer, e.getValue(), e.getKey());
}
}
return platformMBeanServer;
}
......@@ -825,4 +832,24 @@ public class ManagementFactory {
}
}
/**
* Registers a DynamicMBean.
*/
private static void addDynamicMBean(final MBeanServer mbs,
final DynamicMBean dmbean,
final ObjectName on) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException {
mbs.registerMBean(dmbean, on);
return null;
}
});
} catch (PrivilegedActionException e) {
throw new RuntimeException(e.getException());
}
}
}
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.management;
/**
* Diagnostic Command Argument information. It contains the description
* of one parameter of the diagnostic command. A parameter can either be an
* option or an argument. Options are identified by the option name while
* arguments are identified by their position in the command line. The generic
* syntax of a diagnostic command is:
* <blockquote>
* &lt;command name&gt; [&lt;option&gt;=&lt;value&gt;] [&lt;argument_value&gt;]
* </blockquote>
* Example:
* <blockquote>
* command_name option1=value1 option2=value argumentA argumentB argumentC
* </blockquote>
* In this command line, the diagnostic command receives five parameters, two
* options named {@code option1} and {@code option2}, and three arguments.
* argumentA's position is 0, argumentB's position is 1 and argumentC's
* position is 2.
*
* @since 8
*/
class DiagnosticCommandArgumentInfo {
private final String name;
private final String description;
private final String type;
private final String defaultValue;
private final boolean mandatory;
private final boolean option;
private final boolean multiple;
private final int position;
/**
* Returns the argument name.
*
* @return the argument name
*/
String getName() {
return name;
}
/**
* Returns the argument description.
*
* @return the argument description
*/
String getDescription() {
return description;
}
/**
* Returns the argument type.
*
* @return the argument type
*/
String getType() {
return type;
}
/**
* Returns the default value as a String if a default value
* is defined, null otherwise.
*
* @return the default value as a String if a default value
* is defined, null otherwise.
*/
String getDefault() {
return defaultValue;
}
/**
* Returns {@code true} if the argument is mandatory,
* {@code false} otherwise.
*
* @return {@code true} if the argument is mandatory,
* {@code false} otherwise
*/
boolean isMandatory() {
return mandatory;
}
/**
* Returns {@code true} if the argument is an option,
* {@code false} otherwise. Options have to be specified using the
* &lt;key&gt;=&lt;value&gt; syntax on the command line, while other
* arguments are specified with a single &lt;value&gt; field and are
* identified by their position on command line.
*
* @return {@code true} if the argument is an option,
* {@code false} otherwise
*/
boolean isOption() {
return option;
}
/**
* Returns {@code true} if the argument can be specified multiple times,
* {@code false} otherwise.
*
* @return {@code true} if the argument can be specified multiple times,
* {@code false} otherwise
*/
boolean isMultiple() {
return multiple;
}
/**
* Returns the expected position of this argument if it is not an option,
* -1 otherwise. Argument position if defined from left to right,
* starting at zero and ignoring the diagnostic command name and
* options.
*
* @return the expected position of this argument if it is not an option,
* -1 otherwise.
*/
int getPosition() {
return position;
}
DiagnosticCommandArgumentInfo(String name, String description,
String type, String defaultValue,
boolean mandatory, boolean option,
boolean multiple, int position) {
this.name = name;
this.description = description;
this.type = type;
this.defaultValue = defaultValue;
this.mandatory = mandatory;
this.option = option;
this.multiple = multiple;
this.position = position;
}
}
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.management;
import com.sun.management.DiagnosticCommandMBean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.Permission;
import java.util.*;
import javax.management.*;
/**
* Implementation class for the diagnostic commands subsystem.
*
* @since 8
*/
class DiagnosticCommandImpl extends NotificationEmitterSupport
implements DiagnosticCommandMBean {
private final VMManagement jvm;
private volatile Map<String, Wrapper> wrappers = null;
private static final String strClassName = "".getClass().getName();
private static final String strArrayClassName = String[].class.getName();
private final boolean isSupported;
@Override
public Object getAttribute(String attribute) throws AttributeNotFoundException,
MBeanException, ReflectionException {
throw new AttributeNotFoundException(attribute);
}
@Override
public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
InvalidAttributeValueException, MBeanException, ReflectionException {
throw new AttributeNotFoundException(attribute.getName());
}
@Override
public AttributeList getAttributes(String[] attributes) {
return new AttributeList();
}
@Override
public AttributeList setAttributes(AttributeList attributes) {
return new AttributeList();
}
private class Wrapper {
String name;
String cmd;
DiagnosticCommandInfo info;
Permission permission;
Wrapper(String name, String cmd, DiagnosticCommandInfo info)
throws InstantiationException {
this.name = name;
this.cmd = cmd;
this.info = info;
this.permission = null;
Exception cause = null;
if (info.getPermissionClass() != null) {
try {
Class c = Class.forName(info.getPermissionClass());
if (info.getPermissionAction() == null) {
try {
Constructor constructor = c.getConstructor(String.class);
permission = (Permission) constructor.newInstance(info.getPermissionName());
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException ex) {
cause = ex;
}
}
if (permission == null) {
try {
Constructor constructor = c.getConstructor(String.class, String.class);
permission = (Permission) constructor.newInstance(
info.getPermissionName(),
info.getPermissionAction());
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException ex) {
cause = ex;
}
}
} catch (ClassNotFoundException ex) { }
if (permission == null) {
InstantiationException iex =
new InstantiationException("Unable to instantiate required permission");
iex.initCause(cause);
}
}
}
public String execute(String[] args) {
if (permission != null) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(permission);
}
}
if(args == null) {
return executeDiagnosticCommand(cmd);
} else {
StringBuilder sb = new StringBuilder();
sb.append(cmd);
for(int i=0; i<args.length; i++) {
if(args[i] == null) {
throw new IllegalArgumentException("Invalid null argument");
}
sb.append(" ");
sb.append(args[i]);
}
return executeDiagnosticCommand(sb.toString());
}
}
}
DiagnosticCommandImpl(VMManagement jvm) {
this.jvm = jvm;
isSupported = jvm.isRemoteDiagnosticCommandsSupported();
}
private static class OperationInfoComparator implements Comparator<MBeanOperationInfo> {
@Override
public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) {
return o1.getName().compareTo(o2.getName());
}
}
@Override
public MBeanInfo getMBeanInfo() {
SortedSet<MBeanOperationInfo> operations = new TreeSet<>(new OperationInfoComparator());
Map<String, Wrapper> wrappersmap;
if (!isSupported) {
wrappersmap = (Map<String, Wrapper>) Collections.EMPTY_MAP;
} else {
try {
String[] command = getDiagnosticCommands();
DiagnosticCommandInfo[] info = getDiagnosticCommandInfo(command);
MBeanParameterInfo stringArgInfo[] = new MBeanParameterInfo[]{
new MBeanParameterInfo("arguments", strArrayClassName,
"Array of Diagnostic Commands Arguments and Options")
};
wrappersmap = new HashMap<>();
for (int i = 0; i < command.length; i++) {
String name = transform(command[i]);
try {
Wrapper w = new Wrapper(name, command[i], info[i]);
wrappersmap.put(name, w);
operations.add(new MBeanOperationInfo(
w.name,
w.info.getDescription(),
(w.info.getArgumentsInfo() == null
|| w.info.getArgumentsInfo().isEmpty())
? null : stringArgInfo,
strClassName,
MBeanOperationInfo.ACTION_INFO,
commandDescriptor(w)));
} catch (InstantiationException ex) {
// If for some reasons the creation of a diagnostic command
// wrappers fails, the diagnostic command is just ignored
// and won't appear in the DynamicMBean
}
}
} catch (IllegalArgumentException | UnsupportedOperationException e) {
wrappersmap = (Map<String, Wrapper>) Collections.EMPTY_MAP;
}
}
wrappers = Collections.unmodifiableMap(wrappersmap);
HashMap<String, Object> map = new HashMap<>();
map.put("immutableInfo", "false");
map.put("interfaceClassName","com.sun.management.DiagnosticCommandMBean");
map.put("mxbean", "false");
Descriptor desc = new ImmutableDescriptor(map);
return new MBeanInfo(
this.getClass().getName(),
"Diagnostic Commands",
null, // attributes
null, // constructors
operations.toArray(new MBeanOperationInfo[operations.size()]), // operations
getNotificationInfo(), // notifications
desc);
}
@Override
public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
if (!isSupported) {
throw new UnsupportedOperationException();
}
if (wrappers == null) {
getMBeanInfo();
}
Wrapper w = wrappers.get(actionName);
if (w != null) {
if (w.info.getArgumentsInfo().isEmpty()
&& (params == null || params.length == 0)
&& (signature == null || signature.length == 0)) {
return w.execute(null);
} else if((params != null && params.length == 1)
&& (signature != null && signature.length == 1
&& signature[0] != null
&& signature[0].compareTo(strArrayClassName) == 0)) {
return w.execute((String[]) params[0]);
}
}
throw new ReflectionException(new NoSuchMethodException(actionName));
}
private static String transform(String name) {
StringBuilder sb = new StringBuilder();
boolean toLower = true;
boolean toUpper = false;
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (c == '.' || c == '_') {
toLower = false;
toUpper = true;
} else {
if (toUpper) {
toUpper = false;
sb.append(Character.toUpperCase(c));
} else if(toLower) {
sb.append(Character.toLowerCase(c));
} else {
sb.append(c);
}
}
}
return sb.toString();
}
private Descriptor commandDescriptor(Wrapper w) throws IllegalArgumentException {
HashMap<String, Object> map = new HashMap<>();
map.put("dcmd.name", w.info.getName());
map.put("dcmd.description", w.info.getDescription());
map.put("dcmd.vmImpact", w.info.getImpact());
map.put("dcmd.permissionClass", w.info.getPermissionClass());
map.put("dcmd.permissionName", w.info.getPermissionName());
map.put("dcmd.permissionAction", w.info.getPermissionAction());
map.put("dcmd.enabled", w.info.isEnabled());
StringBuilder sb = new StringBuilder();
sb.append("help ");
sb.append(w.info.getName());
map.put("dcmd.help", executeDiagnosticCommand(sb.toString()));
if (w.info.getArgumentsInfo() != null && !w.info.getArgumentsInfo().isEmpty()) {
HashMap<String, Object> allargmap = new HashMap<>();
for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) {
HashMap<String, Object> argmap = new HashMap<>();
argmap.put("dcmd.arg.name", arginfo.getName());
argmap.put("dcmd.arg.type", arginfo.getType());
argmap.put("dcmd.arg.description", arginfo.getDescription());
argmap.put("dcmd.arg.isMandatory", arginfo.isMandatory());
argmap.put("dcmd.arg.isMultiple", arginfo.isMultiple());
boolean isOption = arginfo.isOption();
argmap.put("dcmd.arg.isOption", isOption);
if(!isOption) {
argmap.put("dcmd.arg.position", arginfo.getPosition());
} else {
argmap.put("dcmd.arg.position", -1);
}
allargmap.put(arginfo.getName(), new ImmutableDescriptor(argmap));
}
map.put("dcmd.arguments", new ImmutableDescriptor(allargmap));
}
return new ImmutableDescriptor(map);
}
private final static String notifName =
"javax.management.Notification";
private final static String[] diagFramNotifTypes = {
"jmx.mbean.info.changed"
};
private MBeanNotificationInfo[] notifInfo = null;
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
synchronized (this) {
if (notifInfo == null) {
notifInfo = new MBeanNotificationInfo[1];
notifInfo[0] =
new MBeanNotificationInfo(diagFramNotifTypes,
notifName,
"Diagnostic Framework Notification");
}
}
return notifInfo;
}
private static long seqNumber = 0;
private static long getNextSeqNumber() {
return ++seqNumber;
}
private void createDiagnosticFrameworkNotification() {
if (!hasListeners()) {
return;
}
ObjectName on = null;
try {
on = ObjectName.getInstance(ManagementFactoryHelper.HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME);
} catch (MalformedObjectNameException e) { }
Notification notif = new Notification("jmx.mbean.info.changed",
on,
getNextSeqNumber());
notif.setUserData(getMBeanInfo());
sendNotification(notif);
}
@Override
public synchronized void addNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback) {
boolean before = hasListeners();
super.addNotificationListener(listener, filter, handback);
boolean after = hasListeners();
if (!before && after) {
setNotificationEnabled(true);
}
}
@Override
public synchronized void removeNotificationListener(NotificationListener listener)
throws ListenerNotFoundException {
boolean before = hasListeners();
super.removeNotificationListener(listener);
boolean after = hasListeners();
if (before && !after) {
setNotificationEnabled(false);
}
}
@Override
public synchronized void removeNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback)
throws ListenerNotFoundException {
boolean before = hasListeners();
super.removeNotificationListener(listener, filter, handback);
boolean after = hasListeners();
if (before && !after) {
setNotificationEnabled(false);
}
}
private native void setNotificationEnabled(boolean enabled);
private native String[] getDiagnosticCommands();
private native DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands);
private native String executeDiagnosticCommand(String command);
}
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.management;
import java.util.List;
/**
* Diagnostic command information. It contains the description of a
* diagnostic command.
*
* @since 8
*/
class DiagnosticCommandInfo {
private final String name;
private final String description;
private final String impact;
private final String permissionClass;
private final String permissionName;
private final String permissionAction;
private final boolean enabled;
private final List<DiagnosticCommandArgumentInfo> arguments;
/**
* Returns the diagnostic command name.
*
* @return the diagnostic command name
*/
String getName() {
return name;
}
/**
* Returns the diagnostic command description.
*
* @return the diagnostic command description
*/
String getDescription() {
return description;
}
/**
* Returns the potential impact of the diagnostic command execution
* on the Java virtual machine behavior.
*
* @return the potential impact of the diagnostic command execution
* on the Java virtual machine behavior
*/
String getImpact() {
return impact;
}
/**
* Returns the name of the permission class required to be allowed
* to invoke the diagnostic command, or null if no permission
* is required.
*
* @return the name of the permission class name required to be allowed
* to invoke the diagnostic command, or null if no permission
* is required
*/
String getPermissionClass() {
return permissionClass;
}
/**
* Returns the permission name required to be allowed to invoke the
* diagnostic command, or null if no permission is required.
*
* @return the permission name required to be allowed to invoke the
* diagnostic command, or null if no permission is required
*/
String getPermissionName() {
return permissionName;
}
/**
* Returns the permission action required to be allowed to invoke the
* diagnostic command, or null if no permission is required or
* if the permission has no action specified.
*
* @return the permission action required to be allowed to invoke the
* diagnostic command, or null if no permission is required or
* if the permission has no action specified
*/
String getPermissionAction() {
return permissionAction;
}
/**
* Returns {@code true} if the diagnostic command is enabled,
* {@code false} otherwise. The enabled/disabled
* status of a diagnostic command can evolve during
* the lifetime of the Java virtual machine.
*
* @return {@code true} if the diagnostic command is enabled,
* {@code false} otherwise
*/
boolean isEnabled() {
return enabled;
}
/**
* Returns the list of the diagnostic command arguments description.
* If the diagnostic command has no arguments, it returns an empty list.
*
* @return a list of the diagnostic command arguments description
*/
List<DiagnosticCommandArgumentInfo> getArgumentsInfo() {
return arguments;
}
DiagnosticCommandInfo(String name, String description,
String impact, String permissionClass,
String permissionName, String permissionAction,
boolean enabled,
List<DiagnosticCommandArgumentInfo> arguments)
{
this.name = name;
this.description = description;
this.impact = impact;
this.permissionClass = permissionClass;
this.permissionName = permissionName;
this.permissionAction = permissionAction;
this.enabled = enabled;
this.arguments = arguments;
}
}
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -27,6 +27,7 @@ package sun.management;
import java.lang.management.*;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
......@@ -42,7 +43,9 @@ import sun.util.logging.LoggingSupport;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import com.sun.management.DiagnosticCommandMBean;
import com.sun.management.OSMBeanFactory;
import com.sun.management.HotSpotDiagnosticMXBean;
......@@ -263,6 +266,7 @@ public class ManagementFactoryHelper {
private static HotspotThread hsThreadMBean = null;
private static HotspotCompilation hsCompileMBean = null;
private static HotspotMemory hsMemoryMBean = null;
private static DiagnosticCommandImpl hsDiagCommandMBean = null;
public static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() {
if (hsDiagMBean == null) {
......@@ -311,6 +315,14 @@ public class ManagementFactoryHelper {
return hsMemoryMBean;
}
public static synchronized DiagnosticCommandMBean getDiagnosticCommandMBean() {
// Remote Diagnostic Commands may not be supported
if (hsDiagCommandMBean == null && jvm.isRemoteDiagnosticCommandsSupported()) {
hsDiagCommandMBean = new DiagnosticCommandImpl(jvm);
}
return hsDiagCommandMBean;
}
/**
* This method is for testing only.
*/
......@@ -365,6 +377,18 @@ public class ManagementFactoryHelper {
private final static String HOTSPOT_THREAD_MBEAN_NAME =
"sun.management:type=HotspotThreading";
final static String HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME =
"com.sun.management:type=DiagnosticCommand";
public static HashMap<ObjectName, DynamicMBean> getPlatformDynamicMBeans() {
HashMap<ObjectName, DynamicMBean> map = new HashMap<>();
DiagnosticCommandMBean diagMBean = getDiagnosticCommandMBean();
if (diagMBean != null) {
map.put(Util.newObjectName(HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME), diagMBean);
}
return map;
}
static void registerInternalMBeans(MBeanServer mbs) {
// register all internal MBeans if not registered
// No exception is thrown if a MBean with that object name
......
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -46,6 +46,7 @@ public interface VMManagement {
public boolean isThreadAllocatedMemorySupported();
public boolean isThreadAllocatedMemoryEnabled();
public boolean isGcNotificationSupported();
public boolean isRemoteDiagnosticCommandsSupported();
// Class Loading Subsystem
public long getTotalClassCount();
......
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -57,6 +57,7 @@ class VMManagementImpl implements VMManagement {
private static boolean synchronizerUsageSupport;
private static boolean threadAllocatedMemorySupport;
private static boolean gcNotificationSupport;
private static boolean remoteDiagnosticCommandsSupport;
static {
......@@ -106,6 +107,10 @@ class VMManagementImpl implements VMManagement {
return gcNotificationSupport;
}
public boolean isRemoteDiagnosticCommandsSupported() {
return remoteDiagnosticCommandsSupport;
}
public native boolean isThreadContentionMonitoringEnabled();
public native boolean isThreadCpuTimeEnabled();
public native boolean isThreadAllocatedMemoryEnabled();
......
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -49,7 +49,8 @@ enum {
JMM_VERSION_1_1 = 0x20010100, // JDK 6
JMM_VERSION_1_2 = 0x20010200, // JDK 7
JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA
JMM_VERSION = 0x20010202
JMM_VERSION_1_2_2 = 0x20010202,
JMM_VERSION = 0x20010203
};
typedef struct {
......@@ -62,7 +63,8 @@ typedef struct {
unsigned int isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1;
unsigned int isThreadAllocatedMemorySupported : 1;
unsigned int : 23;
unsigned int isRemoteDiagnosticCommandsSupported : 1;
unsigned int : 22;
} jmmOptionalSupport;
typedef enum {
......@@ -190,21 +192,27 @@ typedef struct {
} jmmGCStat;
typedef struct {
const char* name;
const char* description;
const char* impact;
int num_arguments;
jboolean enabled;
const char* name; /* Name of the diagnostic command */
const char* description; /* Short description */
const char* impact; /* Impact on the JVM */
const char* permission_class; /* Class name of the required permission if any */
const char* permission_name; /* Permission name of the required permission if any */
const char* permission_action; /* Action name of the required permission if any*/
int num_arguments; /* Number of supported options or arguments */
jboolean enabled; /* True if the diagnostic command can be invoked, false otherwise*/
} dcmdInfo;
typedef struct {
const char* name;
const char* description;
const char* type;
const char* default_string;
jboolean mandatory;
jboolean option;
int position;
const char* name; /* Option/Argument name*/
const char* description; /* Short description */
const char* type; /* Type: STRING, BOOLEAN, etc. */
const char* default_string; /* Default value in a parsable string */
jboolean mandatory; /* True if the option/argument is mandatory */
jboolean option; /* True if it is an option, false if it is an argument */
/* (see diagnosticFramework.hpp for option/argument definitions) */
jboolean multiple; /* True is the option can be specified several time */
int position; /* Expected position for this argument (this field is */
/* meaningless for options) */
} dcmdArgInfo;
typedef struct jmmInterface_1_ {
......@@ -327,6 +335,9 @@ typedef struct jmmInterface_1_ {
jstring (JNICALL *ExecuteDiagnosticCommand)
(JNIEnv *env,
jstring command);
void (JNICALL *SetDiagnosticFrameworkNotificationEnabled)
(JNIEnv *env,
jboolean enabled);
} JmmInterface;
#ifdef __cplusplus
......
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
#include <jni.h>
#include "management.h"
#include "sun_management_DiagnosticCommandImpl.h"
JNIEXPORT void JNICALL Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled
(JNIEnv *env, jobject dummy, jboolean enabled) {
if(jmm_version > JMM_VERSION_1_2_2) {
jmm_interface->SetDiagnosticFrameworkNotificationEnabled(env, enabled);
} else {
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
"JMX interface to diagnostic framework notifications is not supported by this VM");
}
}
JNIEXPORT jobjectArray JNICALL
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands
(JNIEnv *env, jobject dummy)
{
return jmm_interface->GetDiagnosticCommands(env);
}
jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command,
int num_arg) {
int i;
jobject obj;
jobjectArray result;
dcmdArgInfo* dcmd_arg_info_array;
jclass dcmdArgInfoCls;
jclass arraysCls;
jmethodID mid;
jobject resultList;
dcmd_arg_info_array = (dcmdArgInfo*) malloc(num_arg * sizeof(dcmdArgInfo));
if (dcmd_arg_info_array == NULL) {
return NULL;
}
jmm_interface->GetDiagnosticCommandArgumentsInfo(env, command,
dcmd_arg_info_array);
dcmdArgInfoCls = (*env)->FindClass(env,
"sun/management/DiagnosticCommandArgumentInfo");
result = (*env)->NewObjectArray(env, num_arg, dcmdArgInfoCls, NULL);
if (result == NULL) {
free(dcmd_arg_info_array);
return NULL;
}
for (i=0; i<num_arg; i++) {
obj = JNU_NewObjectByName(env,
"sun/management/DiagnosticCommandArgumentInfo",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZI)V",
(*env)->NewStringUTF(env,dcmd_arg_info_array[i].name),
(*env)->NewStringUTF(env,dcmd_arg_info_array[i].description),
(*env)->NewStringUTF(env,dcmd_arg_info_array[i].type),
dcmd_arg_info_array[i].default_string == NULL ? NULL:
(*env)->NewStringUTF(env, dcmd_arg_info_array[i].default_string),
dcmd_arg_info_array[i].mandatory,
dcmd_arg_info_array[i].option,
dcmd_arg_info_array[i].multiple,
dcmd_arg_info_array[i].position);
if (obj == NULL) {
free(dcmd_arg_info_array);
return NULL;
}
(*env)->SetObjectArrayElement(env, result, i, obj);
}
free(dcmd_arg_info_array);
arraysCls = (*env)->FindClass(env, "java/util/Arrays");
mid = (*env)->GetStaticMethodID(env, arraysCls,
"asList", "([Ljava/lang/Object;)Ljava/util/List;");
resultList = (*env)->CallStaticObjectMethod(env, arraysCls, mid, result);
return resultList;
}
/* Throws IllegalArgumentException if at least one of the diagnostic command
* passed in argument is not supported by the JVM
*/
JNIEXPORT jobjectArray JNICALL
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo
(JNIEnv *env, jobject dummy, jobjectArray commands)
{
int i;
jclass dcmdInfoCls;
jobject result;
jobjectArray args;
jobject obj;
jmmOptionalSupport mos;
jint ret = jmm_interface->GetOptionalSupport(env, &mos);
jsize num_commands;
dcmdInfo* dcmd_info_array;
if (commands == NULL) {
JNU_ThrowNullPointerException(env, "Invalid String Array");
return NULL;
}
num_commands = (*env)->GetArrayLength(env, commands);
dcmd_info_array = (dcmdInfo*) malloc(num_commands *
sizeof(dcmdInfo));
if (dcmd_info_array == NULL) {
JNU_ThrowOutOfMemoryError(env, NULL);
}
jmm_interface->GetDiagnosticCommandInfo(env, commands, dcmd_info_array);
dcmdInfoCls = (*env)->FindClass(env,
"sun/management/DiagnosticCommandInfo");
result = (*env)->NewObjectArray(env, num_commands, dcmdInfoCls, NULL);
if (result == NULL) {
free(dcmd_info_array);
JNU_ThrowOutOfMemoryError(env, 0);
}
for (i=0; i<num_commands; i++) {
args = getDiagnosticCommandArgumentInfoArray(env,
(*env)->GetObjectArrayElement(env,commands,i),
dcmd_info_array[i].num_arguments);
if (args == NULL) {
free(dcmd_info_array);
JNU_ThrowOutOfMemoryError(env, 0);
}
obj = JNU_NewObjectByName(env,
"sun/management/DiagnosticCommandInfo",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/util/List;)V",
(*env)->NewStringUTF(env,dcmd_info_array[i].name),
(*env)->NewStringUTF(env,dcmd_info_array[i].description),
(*env)->NewStringUTF(env,dcmd_info_array[i].impact),
dcmd_info_array[i].permission_class==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_class),
dcmd_info_array[i].permission_name==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_name),
dcmd_info_array[i].permission_action==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_action),
dcmd_info_array[i].enabled,
args);
if (obj == NULL) {
free(dcmd_info_array);
JNU_ThrowOutOfMemoryError(env, 0);
}
(*env)->SetObjectArrayElement(env, result, i, obj);
}
free(dcmd_info_array);
return result;
}
/* Throws IllegalArgumentException if the diagnostic command
* passed in argument is not supported by the JVM
*/
JNIEXPORT jstring JNICALL
Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand
(JNIEnv *env, jobject dummy, jstring command) {
return jmm_interface->ExecuteDiagnosticCommand(env, command);
}
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -24,6 +24,7 @@
*/
#include <jni.h>
#include <stdlib.h>
#include "jvm.h"
#include "management.h"
#include "sun_management_VMManagementImpl.h"
......@@ -96,6 +97,9 @@ Java_sun_management_VMManagementImpl_initOptionalSupportFields
value = mos.isThreadAllocatedMemorySupported;
setStaticBooleanField(env, cls, "threadAllocatedMemorySupport", value);
value = mos.isRemoteDiagnosticCommandsSupported;
setStaticBooleanField(env, cls, "remoteDiagnosticCommandsSupport", value);
if ((jmm_version > JMM_VERSION_1_2) ||
(jmm_version == JMM_VERSION_1_2 && ((jmm_version&0xFF) >= 1))) {
setStaticBooleanField(env, cls, "gcNotificationSupport", JNI_TRUE);
......
/*
* Copyright (c) 2013, 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 7150256
* @summary Basic Test for the DiagnosticCommandMBean
* @author Frederic Parain
*
* @run main/othervm -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8125 DcmdMBeanDoubleInvocationTest
*/
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.Descriptor;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.*;
import javax.management.remote.*;
public class DcmdMBeanDoubleInvocationTest {
private static String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
"com.sun.management:type=DiagnosticCommand";
public static void main(String[] args) {
MBeanServerConnection mbs = null;
try {
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8125/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(url);
mbs = connector.getMBeanServerConnection();
} catch(Throwable t) {
t.printStackTrace();
}
ObjectName name;
try {
name = new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME);
MBeanInfo info = mbs.getMBeanInfo(name);
String[] helpArgs = {"-all", "\n", "VM.version"};
Object[] dcmdArgs = {helpArgs};
String[] signature = {String[].class.getName()};
String result = (String) mbs.invoke(name, "help", dcmdArgs, signature);
System.out.println(result);
} catch (RuntimeMBeanException ex) {
if (ex.getCause() instanceof IllegalArgumentException) {
System.out.println("Test passed");
return;
} else {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
} catch (InstanceNotFoundException | IntrospectionException
| ReflectionException | MalformedObjectNameException
| MBeanException|IOException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
System.out.println("Double commands have not been detected");
throw new RuntimeException("TEST FAILED");
}
}
/*
* Copyright (c) 2013, 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 7150256
* @summary Basic Test for the DiagnosticCommandMBean
* @author Frederic Parain
*
* @run main/othervm -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8129 DcmdMBeanInvocationTest
*/
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.Descriptor;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.*;
import javax.management.remote.*;
public class DcmdMBeanInvocationTest {
private static String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
"com.sun.management:type=DiagnosticCommand";
public static void main(String[] args) {
MBeanServerConnection mbs = null;
try {
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8129/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(url);
mbs = connector.getMBeanServerConnection();
} catch(Throwable t) {
t.printStackTrace();
}
ObjectName name;
try {
name = new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME);
MBeanInfo info = mbs.getMBeanInfo(name);
String[] helpArgs = {"-all"};
Object[] dcmdArgs = {helpArgs};
String[] signature = {String[].class.getName()};
String result = (String) mbs.invoke(name, "help", dcmdArgs, signature);
System.out.println(result);
} catch (InstanceNotFoundException | IntrospectionException
| ReflectionException | MalformedObjectNameException
| MBeanException|IOException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
System.out.println("Test passed");
}
}
/*
* Copyright (c) 2013, 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 7150256
* @summary Permissions Tests for the DiagnosticCommandMBean
* @author Frederic Parain
*
* @run main/othervm DcmdMBeanPermissionsTest
*/
import java.lang.management.ManagementFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ReflectPermission;
import java.security.Permission;
import java.util.HashSet;
import java.util.Iterator;
import javax.management.Descriptor;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanPermission;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.RuntimeMBeanException;
/**
*
* @author fparain
*/
public class DcmdMBeanPermissionsTest {
private static String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
"com.sun.management:type=DiagnosticCommand";
static public class CustomSecurityManager extends SecurityManager {
private HashSet<Permission> grantedPermissions;
public CustomSecurityManager() {
grantedPermissions = new HashSet<Permission>();
}
public final void grantPermission(final Permission perm) {
grantedPermissions.add(perm);
}
public final void denyPermission(final Permission perm) {
Iterator<Permission> it = grantedPermissions.iterator();
while (it.hasNext()) {
Permission p = it.next();
if (p.equals(perm)) {
it.remove();
}
}
}
public final void checkPermission(final Permission perm) {
for (Permission p : grantedPermissions) {
if (p.implies(perm)) {
return;
}
}
throw new SecurityException(perm.toString());
}
};
static Permission createPermission(String classname, String name,
String action) {
Permission permission = null;
try {
Class c = Class.forName(classname);
if (action == null) {
try {
Constructor constructor = c.getConstructor(String.class);
permission = (Permission) constructor.newInstance(name);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
}
if (permission == null) {
try {
Constructor constructor = c.getConstructor(String.class,
String.class);
permission = (Permission) constructor.newInstance(
name,
action);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
}
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
if (permission == null) {
throw new RuntimeException("TEST FAILED");
}
return permission;
}
// return true if invokation triggered a SecurityException
static boolean invokeOperation(MBeanServer mbs, ObjectName on,
MBeanOperationInfo opInfo) {
try {
if (opInfo.getSignature().length == 0) {
mbs.invoke(on, opInfo.getName(),
new Object[0], new String[0]);
} else {
mbs.invoke(on, opInfo.getName(),
new Object[1], new String[]{ String[].class.getName()});
}
} catch (SecurityException ex) {
ex.printStackTrace();
return true;
} catch (RuntimeMBeanException ex) {
if (ex.getCause() instanceof SecurityException) {
//ex.printStackTrace();
return true;
}
} catch (MBeanException | InstanceNotFoundException
| ReflectionException ex) {
throw new RuntimeException("TEST FAILED");
}
return false;
}
static void testOperation(MBeanServer mbs, CustomSecurityManager sm,
ObjectName on, MBeanOperationInfo opInfo) {
System.out.println("Testing " + opInfo.getName());
Descriptor desc = opInfo.getDescriptor();
if (desc.getFieldValue("dcmd.permissionClass") == null) {
// No special permission required, execution should not trigger
// any security exception
if (invokeOperation(mbs, on, opInfo)) {
throw new RuntimeException("TEST FAILED");
}
} else {
// Building the required permission
Permission reqPerm = createPermission(
(String)desc.getFieldValue("dcmd.permissionClass"),
(String)desc.getFieldValue("dcmd.permissionName"),
(String)desc.getFieldValue("dcmd.permissionAction"));
// Paranoid mode: check that the SecurityManager has not already
// been granted the permission
sm.denyPermission(reqPerm);
// A special permission is required for this operation,
// invoking it without the permission granted must trigger
// a security exception
if(!invokeOperation(mbs, on, opInfo)) {
throw new RuntimeException("TEST FAILED");
}
// grant the permission and re-try invoking the operation
sm.grantPermission(reqPerm);
if(invokeOperation(mbs, on, opInfo)) {
throw new RuntimeException("TEST FAILED");
}
// Clean up
sm.denyPermission(reqPerm);
}
}
public static void main(final String[] args) {
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName on = null;
try {
on = new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME);
} catch (MalformedObjectNameException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
MBeanInfo info = null;
try {
info = mbs.getMBeanInfo(on);
} catch (InstanceNotFoundException | IntrospectionException
| ReflectionException ex) {
ex.printStackTrace();
throw new RuntimeException("TEST FAILED");
}
CustomSecurityManager sm = new CustomSecurityManager();
System.setSecurityManager(sm);
// Set of permission required to run the test cleanly
// Some permissions are required by the MBeanServer and other
// platform services (RuntimePermission("createClassLoader"),
// ReflectPermission("suppressAccessChecks"),
// java.util.logging.LoggingPermission("control"),
// RuntimePermission("exitVM.97")).
// Other permissions are required by commands being invoked
// in the test (for instance, RuntimePermission("modifyThreadGroup")
// and RuntimePermission("modifyThread") are checked when
// runFinalization() is invoked by the gcRunFinalization command.
sm.grantPermission(new RuntimePermission("createClassLoader"));
sm.grantPermission(new ReflectPermission("suppressAccessChecks"));
sm.grantPermission(new java.util.logging.LoggingPermission("control", ""));
sm.grantPermission(new java.lang.RuntimePermission("exitVM.97"));
sm.grantPermission(new java.lang.RuntimePermission("modifyThreadGroup"));
sm.grantPermission(new java.lang.RuntimePermission("modifyThread"));
for(MBeanOperationInfo opInfo : info.getOperations()) {
Permission opPermission = new MBeanPermission(info.getClassName(),
opInfo.getName(),
on,
"invoke");
sm.grantPermission(opPermission);
testOperation(mbs, sm, on, opInfo);
sm.denyPermission(opPermission);
}
System.out.println("TEST PASSED");
}
}
/*
* Copyright (c) 2013, 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 7150256
* @summary Basic Test for the DiagnosticCommandMBean
* @author Frederic Parain
*
* @run main/othervm -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8127 DcmdMBeanTest
*/
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.Descriptor;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.*;
import javax.management.remote.*;
public class DcmdMBeanTest {
private static String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
"com.sun.management:type=DiagnosticCommand";
public static void main(String[] args) {
MBeanServerConnection mbs = null;
try {
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8127/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(url);
mbs = connector.getMBeanServerConnection();
} catch(Throwable t) {
t.printStackTrace();
}
ObjectName name;
try {
name = new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME);
MBeanInfo info = mbs.getMBeanInfo(name);
// the test should check that the MBean doesn't have any
// Attribute, notification or constructor. Current version only
// check operations
System.out.println("Class Name:"+info.getClassName());
System.out.println("Description:"+info.getDescription());
MBeanOperationInfo[] opInfo = info.getOperations();
System.out.println("Operations:");
for(int i=0; i<opInfo.length; i++) {
printOperation(opInfo[i]);
System.out.println("\n@@@@@@\n");
}
} catch (InstanceNotFoundException|IntrospectionException|ReflectionException
|MalformedObjectNameException|IOException ex) {
Logger.getLogger(DcmdMBeanTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
static void printOperation(MBeanOperationInfo info) {
System.out.println("Name: "+info.getName());
System.out.println("Description: "+info.getDescription());
System.out.println("Return Type: "+info.getReturnType());
System.out.println("Impact: "+info.getImpact());
Descriptor desc = info.getDescriptor();
System.out.println("Descriptor");
for(int i=0; i<desc.getFieldNames().length; i++) {
if(desc.getFieldNames()[i].compareTo("dcmd.arguments") == 0) {
System.out.println("\t"+desc.getFieldNames()[i]+":");
Descriptor desc2 =
(Descriptor)desc.getFieldValue(desc.getFieldNames()[i]);
for(int j=0; j<desc2.getFieldNames().length; j++) {
System.out.println("\t\t"+desc2.getFieldNames()[j]+"=");
Descriptor desc3 =
(Descriptor)desc2.getFieldValue(desc2.getFieldNames()[j]);
for(int k=0; k<desc3.getFieldNames().length; k++) {
System.out.println("\t\t\t"+desc3.getFieldNames()[k]+"="
+desc3.getFieldValue(desc3.getFieldNames()[k]));
}
}
} else {
System.out.println("\t"+desc.getFieldNames()[i]+"="
+desc.getFieldValue(desc.getFieldNames()[i]));
}
}
}
}
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013 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
......@@ -36,6 +36,10 @@ import java.util.*;
import javax.management.*;
public class MXBeanBehavior {
// Exclude list: list of platform MBeans that are not MXBeans
public static final HashSet<String> excludeList = new HashSet<>(
Arrays.asList("com.sun.management:type=DiagnosticCommand"));
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
......@@ -92,6 +96,10 @@ public class MXBeanBehavior {
by generic MXBean tests.
*/
private static void test(MBeanServer mbs, ObjectName name) throws Exception {
if(excludeList.contains(name.getCanonicalName())) {
// Skipping not MXBean objects.
return;
}
System.out.println("Testing: " + name);
MBeanInfo mbi = mbs.getMBeanInfo(name);
......
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2013 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
......@@ -36,6 +36,8 @@ import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashSet;
import javax.management.MBeanServer;
import javax.management.MBeanServerBuilder;
import javax.management.MBeanServerDelegate;
......@@ -81,6 +83,9 @@ public class MBeanServerMXBeanUnsupportedTest {
public static class MBeanServerForwarderInvocationHandler
implements InvocationHandler {
public static final HashSet<String> excludeList = new HashSet<String>(
Arrays.asList("com.sun.management:type=DiagnosticCommand"));
public static MBeanServerForwarder newProxyInstance() {
final InvocationHandler handler =
......@@ -126,15 +131,17 @@ public class MBeanServerMXBeanUnsupportedTest {
if (domain.equals("java.lang") ||
domain.equals("java.util.logging") ||
domain.equals("com.sun.management")) {
String mxbean = (String)
mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean");
if (mxbean == null || !mxbean.equals("true")) {
throw new RuntimeException(
if(!excludeList.contains(name.getCanonicalName())) {
String mxbean = (String)
mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean");
if (mxbean == null || !mxbean.equals("true")) {
throw new RuntimeException(
"Platform MBeans must be MXBeans!");
}
if (!(mbean instanceof StandardMBean)) {
throw new RuntimeException(
}
if (!(mbean instanceof StandardMBean)) {
throw new RuntimeException(
"MXBeans must be wrapped in StandardMBean!");
}
}
}
return result;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册