changeset 8870:e857b2a3ecee

7150256: Add back Diagnostic Command JMX API Reviewed-by: mchung, jbachorik
author fparain
date Wed, 05 Jun 2013 08:41:02 -0700
parents c1af6b5a979a
children 388b4d4cae3b 571e5f452640 69d566198fe4 733713d7517c
files make/java/management/Exportedfiles.gmk make/java/management/FILES_c.gmk make/java/management/mapfile-vers makefiles/mapfiles/libmanagement/mapfile-vers src/share/classes/com/sun/management/DiagnosticCommandMBean.java src/share/classes/java/lang/management/ManagementFactory.java src/share/classes/sun/management/DiagnosticCommandArgumentInfo.java src/share/classes/sun/management/DiagnosticCommandImpl.java src/share/classes/sun/management/DiagnosticCommandInfo.java src/share/classes/sun/management/ManagementFactoryHelper.java src/share/classes/sun/management/VMManagement.java src/share/classes/sun/management/VMManagementImpl.java src/share/javavm/export/jmm.h src/share/native/sun/management/DiagnosticCommandImpl.c src/share/native/sun/management/VMManagementImpl.c test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanInvocationTest.java test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanPermissionsTest.java test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTest.java test/java/lang/management/MXBean/MXBeanBehavior.java test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java
diffstat 21 files changed, 1735 insertions(+), 33 deletions(-) [+]
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>
+ *    &lt;command name&gt; [&lt;option&gt;=&lt;value&gt;] [&lt;argument_value&gt;]
+ * </blockquote>
+ * Example:
+ * <blockquote>
+ * command_name option1=value1 option2=value argumentA argumentB argumentC
+ * </blockquote>
+ * In this command line, the diagnostic command receives five parameters, two
+ * options named {@code option1} and {@code option2}, and three arguments.
+ * argumentA's position is 0, argumentB's position is 1 and argumentC's
+ * position is 2.
+ *
+ * @since 8
+ */
+
+class DiagnosticCommandArgumentInfo {
+    private final String name;
+    private final String description;
+    private final String type;
+    private final String defaultValue;
+    private final boolean mandatory;
+    private final boolean option;
+    private final boolean multiple;
+    private final int position;
+
+    /**
+     * Returns the argument name.
+     *
+     * @return the argument name
+     */
+    String getName() {
+        return name;
+    }
+
+   /**
+     * Returns the argument description.
+     *
+     * @return the argument description
+     */
+    String getDescription() {
+        return description;
+    }
+
+    /**
+     * Returns the argument type.
+     *
+     * @return the argument type
+     */
+    String getType() {
+        return type;
+    }
+
+    /**
+     * Returns the default value as a String if a default value
+     * is defined, null otherwise.
+     *
+     * @return the default value as a String if a default value
+     * is defined, null otherwise.
+     */
+    String getDefault() {
+        return defaultValue;
+    }
+
+    /**
+     * Returns {@code true} if the argument is mandatory,
+     *         {@code false} otherwise.
+     *
+     * @return {@code true} if the argument is mandatory,
+     *         {@code false} otherwise
+     */
+    boolean isMandatory() {
+        return mandatory;
+    }
+
+    /**
+     * Returns {@code true} if the argument is an option,
+     *         {@code false} otherwise. Options have to be specified using the
+     *         &lt;key&gt;=&lt;value&gt; syntax on the command line, while other
+     *         arguments are specified with a single &lt;value&gt; field and are
+     *         identified by their position on command line.
+     *
+     * @return {@code true} if the argument is an option,
+     *         {@code false} otherwise
+     */
+    boolean isOption() {
+        return option;
+    }
+
+    /**
+     * Returns {@code true} if the argument can be specified multiple times,
+     *         {@code false} otherwise.
+     *
+     * @return {@code true} if the argument can be specified multiple times,
+     *         {@code false} otherwise
+     */
+    boolean isMultiple() {
+        return multiple;
+    }
+
+    /**
+     * Returns the expected position of this argument if it is not an option,
+     *         -1 otherwise. Argument position if defined from left to right,
+     *         starting at zero and ignoring the diagnostic command name and
+     *         options.
+     *
+     * @return the expected position of this argument if it is not an option,
+     *         -1 otherwise.
+     */
+    int getPosition() {
+        return position;
+    }
+
+    DiagnosticCommandArgumentInfo(String name, String description,
+                                         String type, String defaultValue,
+                                         boolean mandatory, boolean option,
+                                         boolean multiple, int position) {
+        this.name = name;
+        this.description = description;
+        this.type = type;
+        this.defaultValue = defaultValue;
+        this.mandatory = mandatory;
+        this.option = option;
+        this.multiple = multiple;
+        this.position = position;
+    }
+}
--- /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;