7150256: Add back Diagnostic Command JMX API
Reviewed-by: mchung, jbachorik
This commit is contained in:
parent
317fbcc0e8
commit
f405277c72
jdk
make/java/management
makefiles/mapfiles/libmanagement
src/share
classes
com/sun/management
java/lang/management
sun/management
javavm/export
native/sun/management
test
com/sun/management/DiagnosticCommandMBean
DcmdMBeanDoubleInvocationTest.javaDcmdMBeanInvocationTest.javaDcmdMBeanPermissionsTest.javaDcmdMBeanTest.java
java/lang/management
@ -1,5 +1,5 @@
|
||||
#
|
||||
# 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 \
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# 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 \
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# 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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# 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;
|
||||
|
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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>
|
||||
* <command name> [<option>=<value>] [<argument_value>]
|
||||
* </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
|
||||
* <key>=<value> syntax on the command line, while other
|
||||
* arguments are specified with a single <value> 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;
|
||||
}
|
||||
}
|
380
jdk/src/share/classes/sun/management/DiagnosticCommandImpl.java
Normal file
380
jdk/src/share/classes/sun/management/DiagnosticCommandImpl.java
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
}
|
151
jdk/src/share/classes/sun/management/DiagnosticCommandInfo.java
Normal file
151
jdk/src/share/classes/sun/management/DiagnosticCommandInfo.java
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
|
169
jdk/src/share/native/sun/management/DiagnosticCommandImpl.c
Normal file
169
jdk/src/share/native/sun/management/DiagnosticCommandImpl.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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);
|
||||
|
90
jdk/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java
Normal file
90
jdk/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user