Mercurial > hg > openjdk > lambda > jdk
changeset 8870:e857b2a3ecee
7150256: Add back Diagnostic Command JMX API
Reviewed-by: mchung, jbachorik
line wrap: on
line diff
--- a/make/java/management/Exportedfiles.gmk Wed Jun 05 16:23:23 2013 +0100 +++ b/make/java/management/Exportedfiles.gmk Wed Jun 05 08:41:02 2013 -0700 @@ -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 \
--- a/make/java/management/FILES_c.gmk Wed Jun 05 16:23:23 2013 +0100 +++ b/make/java/management/FILES_c.gmk Wed Jun 05 08:41:02 2013 -0700 @@ -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 \
--- a/make/java/management/mapfile-vers Wed Jun 05 16:23:23 2013 +0100 +++ b/make/java/management/mapfile-vers Wed Jun 05 08:41:02 2013 -0700 @@ -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 @@ 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;
--- a/makefiles/mapfiles/libmanagement/mapfile-vers Wed Jun 05 16:23:23 2013 +0100 +++ b/makefiles/mapfiles/libmanagement/mapfile-vers Wed Jun 05 08:41:02 2013 -0700 @@ -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 @@ 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/management/DiagnosticCommandMBean.java Wed Jun 05 08:41:02 2013 -0700 @@ -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 +{ + +}
--- a/src/share/classes/java/lang/management/ManagementFactory.java Wed Jun 05 16:23:23 2013 +0100 +++ b/src/share/classes/java/lang/management/ManagementFactory.java Wed Jun 05 08:41:02 2013 -0700 @@ -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 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 @@ } } } + 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 @@ } } + /** + * 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()); + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/management/DiagnosticCommandArgumentInfo.java Wed Jun 05 08:41:02 2013 -0700 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/management/DiagnosticCommandImpl.java Wed Jun 05 08:41:02 2013 -0700 @@ -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); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/management/DiagnosticCommandInfo.java Wed Jun 05 08:41:02 2013 -0700 @@ -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; + } +}
--- a/src/share/classes/sun/management/ManagementFactoryHelper.java Wed Jun 05 16:23:23 2013 +0100 +++ b/src/share/classes/sun/management/ManagementFactoryHelper.java Wed Jun 05 08:41:02 2013 -0700 @@ -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 @@ 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 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 @@ 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 @@ 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 @@ 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
--- a/src/share/classes/sun/management/VMManagement.java Wed Jun 05 16:23:23 2013 +0100 +++ b/src/share/classes/sun/management/VMManagement.java Wed Jun 05 08:41:02 2013 -0700 @@ -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 boolean isThreadAllocatedMemorySupported(); public boolean isThreadAllocatedMemoryEnabled(); public boolean isGcNotificationSupported(); + public boolean isRemoteDiagnosticCommandsSupported(); // Class Loading Subsystem public long getTotalClassCount();
--- a/src/share/classes/sun/management/VMManagementImpl.java Wed Jun 05 16:23:23 2013 +0100 +++ b/src/share/classes/sun/management/VMManagementImpl.java Wed Jun 05 08:41:02 2013 -0700 @@ -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 @@ private static boolean synchronizerUsageSupport; private static boolean threadAllocatedMemorySupport; private static boolean gcNotificationSupport; + private static boolean remoteDiagnosticCommandsSupport; static { @@ -106,6 +107,10 @@ return gcNotificationSupport; } + public boolean isRemoteDiagnosticCommandsSupported() { + return remoteDiagnosticCommandsSupport; + } + public native boolean isThreadContentionMonitoringEnabled(); public native boolean isThreadCpuTimeEnabled(); public native boolean isThreadAllocatedMemoryEnabled();
--- a/src/share/javavm/export/jmm.h Wed Jun 05 16:23:23 2013 +0100 +++ b/src/share/javavm/export/jmm.h Wed Jun 05 08:41:02 2013 -0700 @@ -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 @@ 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 @@ 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 @@ } 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 @@ jstring (JNICALL *ExecuteDiagnosticCommand) (JNIEnv *env, jstring command); + void (JNICALL *SetDiagnosticFrameworkNotificationEnabled) + (JNIEnv *env, + jboolean enabled); } JmmInterface; #ifdef __cplusplus
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/native/sun/management/DiagnosticCommandImpl.c Wed Jun 05 08:41:02 2013 -0700 @@ -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); +}
--- a/src/share/native/sun/management/VMManagementImpl.c Wed Jun 05 16:23:23 2013 +0100 +++ b/src/share/native/sun/management/VMManagementImpl.c Wed Jun 05 08:41:02 2013 -0700 @@ -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 @@ 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java Wed Jun 05 08:41:02 2013 -0700 @@ -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"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanInvocationTest.java Wed Jun 05 08:41:02 2013 -0700 @@ -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"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanPermissionsTest.java Wed Jun 05 08:41:02 2013 -0700 @@ -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"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTest.java Wed Jun 05 08:41:02 2013 -0700 @@ -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])); + } + } + } +} +
--- a/test/java/lang/management/MXBean/MXBeanBehavior.java Wed Jun 05 16:23:23 2013 +0100 +++ b/test/java/lang/management/MXBean/MXBeanBehavior.java Wed Jun 05 08:41:02 2013 -0700 @@ -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 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 @@ 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);
--- a/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java Wed Jun 05 16:23:23 2013 +0100 +++ b/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java Wed Jun 05 08:41:02 2013 -0700 @@ -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.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 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 @@ 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;