diff --git a/make/java/management/Exportedfiles.gmk b/make/java/management/Exportedfiles.gmk
index 0654fb5752655c14a8c423abdd6fcbafb48d8f2b..21f46bd923a75917fed307ec756fb710ef1fe209 100644
--- a/make/java/management/Exportedfiles.gmk
+++ b/make/java/management/Exportedfiles.gmk
@@ -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 \
diff --git a/make/java/management/FILES_c.gmk b/make/java/management/FILES_c.gmk
index 8c5ddce29b5c17b860389841f949ed4917653b6c..f0d0c9c6e439a4ccab7adcc2650dd4d7bf101b73 100644
--- a/make/java/management/FILES_c.gmk
+++ b/make/java/management/FILES_c.gmk
@@ -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 \
diff --git a/make/java/management/mapfile-vers b/make/java/management/mapfile-vers
index 2e87b70746386c67552285d66567c655f678c7ba..63c4fbf03ccd5d90fd7d45b6427f9a2ea4ec25d5 100644
--- a/make/java/management/mapfile-vers
+++ b/make/java/management/mapfile-vers
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,10 @@ SUNWprivate_1.1 {
Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
Java_com_sun_management_UnixOperatingSystem_initialize;
Java_sun_management_ClassLoadingImpl_setVerboseClass;
+ Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand;
+ Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands;
+ Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo;
+ Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled;
Java_sun_management_FileSystemImpl_isAccessUserOnly0;
Java_sun_management_Flag_getAllFlagNames;
Java_sun_management_Flag_getFlags;
diff --git a/makefiles/mapfiles/libmanagement/mapfile-vers b/makefiles/mapfiles/libmanagement/mapfile-vers
index 2e87b70746386c67552285d66567c655f678c7ba..b934fe8b7487b6cbdbeeba9c83dfc2c1dedb062d 100644
--- a/makefiles/mapfiles/libmanagement/mapfile-vers
+++ b/makefiles/mapfiles/libmanagement/mapfile-vers
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,10 @@ SUNWprivate_1.1 {
Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
Java_com_sun_management_UnixOperatingSystem_initialize;
Java_sun_management_ClassLoadingImpl_setVerboseClass;
+ Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand;
+ Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands;
+ Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo;
+ Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled;
Java_sun_management_FileSystemImpl_isAccessUserOnly0;
Java_sun_management_Flag_getAllFlagNames;
Java_sun_management_Flag_getFlags;
diff --git a/src/share/classes/com/sun/management/DiagnosticCommandMBean.java b/src/share/classes/com/sun/management/DiagnosticCommandMBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..da2d510024e70973786fcb4a6b930f193fe86469
--- /dev/null
+++ b/src/share/classes/com/sun/management/DiagnosticCommandMBean.java
@@ -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.
+ *
+ *
The {code DiagnosticCommandMBean} is registered to the
+ * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
+ * platform MBeanServer} as are other platform MBeans.
+ *
+ *
The {@link javax.management.ObjectName ObjectName} for uniquely identifying
+ * the diagnostic MBean within an MBeanServer is:
+ *
+ * {@code com.sun.management:type=DiagnosticCommand}
+ *
+ *
+ * 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 diagnostic command is represented as an operation of
+ * the {@code DiagnosticCommandMBean} interface. Each diagnostic command has:
+ *
+ * - the diagnostic command name which is the name being referenced in
+ * the HotSpot Virtual Machine
+ * - 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
+ *
+ *
+ * The recommended way to transform a diagnostic command name into a MBean
+ * operation name is as follows:
+ *
+ * - All characters from the first one to the first dot are set to be
+ * lower-case characters
+ * - Every dot or underline character is removed and the following
+ * character is set to be an upper-case character
+ * - All other characters are copied without modification
+ *
+ *
+ * The diagnostic command name is always provided with the meta-data on the
+ * operation in a field named {@code dcmd.name} (see below).
+ *
+ *
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.
+ *
+ *
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.
+ *
+ *
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:
+ *
+ * - {@link javax.management.MBeanOperationInfo#getName() getName()}
+ * returns the operation name generated from the diagnostic command name
+ * - {@link javax.management.MBeanOperationInfo#getDescription() getDescription()}
+ * returns the diagnostic command description
+ * (the same as the one return in the 'help' command)
+ * - {@link javax.management.MBeanOperationInfo#getImpact() getImpact()}
+ * returns
ACTION_INFO
+ * - {@link javax.management.MBeanOperationInfo#getReturnType() getReturnType()}
+ * returns {@code java.lang.String}
+ * - {@link javax.management.MBeanOperationInfo#getDescriptor() getDescriptor()}
+ * returns a Descriptor instance (see below)
+ *
+ *
+ * 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:
+ *
+ *
+ *
+ *
+ * Name | Type | Description |
+ *
+ *
+ * dcmd.name | String |
+ * The original diagnostic command name (not the operation name) |
+ *
+ *
+ * dcmd.description | String |
+ * The diagnostic command description |
+ *
+ *
+ * dcmd.help | String |
+ * The full help message for this diagnostic command (same output as
+ * the one produced by the 'help' command) |
+ *
+ *
+ * dcmd.vmImpact | String |
+ * 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 |
+ *
+ *
+ * dcmd.enabled | boolean |
+ * True if the diagnostic command is enabled, false otherwise |
+ *
+ *
+ * dcmd.permissionClass | String |
+ * 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
+ * |
+ *
+ *
+ * dcmd.permissionName | String |
+ * The fist argument of the permission required to execute this
+ * diagnostic command or null if no permission is required |
+ *
+ *
+ * dcmd.permissionAction | String |
+ * 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 |
+ *
+ *
+ * dcmd.arguments | Descriptor |
+ * A Descriptor instance containing the descriptions of options and
+ * arguments supported by the diagnostic command (see below) |
+ *
+ *
+ *
+ *
+ *
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:
+ *
+ *
+ *
+ * Name | Type | Description |
+ *
+ *
+ * dcmd.arg.name | String |
+ * The name of the parameter |
+ *
+ *
+ * dcmd.arg.type | String |
+ * 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.
+ * |
+ *
+ *
+ * dcmd.arg.description | String |
+ * The parameter description |
+ *
+ *
+ * dcmd.arg.isMandatory | boolean |
+ * True if the parameter is mandatory, false otherwise |
+ *
+ *
+ * dcmd.arg.isOption | boolean |
+ * True if the parameter is an option, false if it is an argument |
+ *
+ *
+ * dcmd.arg.isMultiple | boolean |
+ * True if the parameter can be specified several times, false
+ * otherwise |
+ *
+ *
+ *
+ * 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
+ *
+ * {@code "jmx.mbean.info.changed"} and a
+ * {@linkplain javax.management.Notification#getUserData() userData} that
+ * is the new {@code MBeanInfo}.
+ *
+ * @since 8
+ */
+public interface DiagnosticCommandMBean extends DynamicMBean
+{
+
+}
diff --git a/src/share/classes/java/lang/management/ManagementFactory.java b/src/share/classes/java/lang/management/ManagementFactory.java
index 278ace1d7d11cb03f0f97a44ef0bd9590488f4e3..384cf4cda069f38efa94e1b744531f0da14fcba0 100644
--- a/src/share/classes/java/lang/management/ManagementFactory.java
+++ b/src/share/classes/java/lang/management/ManagementFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,9 @@ import javax.management.StandardMBean;
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
@@ -482,6 +484,11 @@ public class ManagementFactory {
}
}
}
+ HashMap dynmbeans =
+ ManagementFactoryHelper.getPlatformDynamicMBeans();
+ for (Map.Entry e : dynmbeans.entrySet()) {
+ addDynamicMBean(platformMBeanServer, e.getValue(), e.getKey());
+ }
}
return platformMBeanServer;
}
@@ -825,4 +832,24 @@ public class ManagementFactory {
}
}
+ /**
+ * Registers a DynamicMBean.
+ */
+ private static void addDynamicMBean(final MBeanServer mbs,
+ final DynamicMBean dmbean,
+ final ObjectName on) {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Void run() throws InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ NotCompliantMBeanException {
+ mbs.registerMBean(dmbean, on);
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new RuntimeException(e.getException());
+ }
+ }
}
diff --git a/src/share/classes/sun/management/DiagnosticCommandArgumentInfo.java b/src/share/classes/sun/management/DiagnosticCommandArgumentInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..37bccb0d3bc6f958c11b92b93efda8c88d63f164
--- /dev/null
+++ b/src/share/classes/sun/management/DiagnosticCommandArgumentInfo.java
@@ -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:
+ *
+ * <command name> [<option>=<value>] [<argument_value>]
+ *
+ * Example:
+ *
+ * command_name option1=value1 option2=value argumentA argumentB argumentC
+ *
+ * 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;
+ }
+}
diff --git a/src/share/classes/sun/management/DiagnosticCommandImpl.java b/src/share/classes/sun/management/DiagnosticCommandImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..eeeee9af053e75674dfd9ec75b73c98ee08e1622
--- /dev/null
+++ b/src/share/classes/sun/management/DiagnosticCommandImpl.java
@@ -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 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 {
+ @Override
+ public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ }
+
+ @Override
+ public MBeanInfo getMBeanInfo() {
+ SortedSet operations = new TreeSet<>(new OperationInfoComparator());
+ Map wrappersmap;
+ if (!isSupported) {
+ wrappersmap = (Map) 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) Collections.EMPTY_MAP;
+ }
+ }
+ wrappers = Collections.unmodifiableMap(wrappersmap);
+ HashMap 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 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 allargmap = new HashMap<>();
+ for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) {
+ HashMap 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);
+
+}
diff --git a/src/share/classes/sun/management/DiagnosticCommandInfo.java b/src/share/classes/sun/management/DiagnosticCommandInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ad0a963bb8166734040b11bca82ed4d4a86e857
--- /dev/null
+++ b/src/share/classes/sun/management/DiagnosticCommandInfo.java
@@ -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 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 getArgumentsInfo() {
+ return arguments;
+ }
+
+ DiagnosticCommandInfo(String name, String description,
+ String impact, String permissionClass,
+ String permissionName, String permissionAction,
+ boolean enabled,
+ List 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;
+ }
+}
diff --git a/src/share/classes/sun/management/ManagementFactoryHelper.java b/src/share/classes/sun/management/ManagementFactoryHelper.java
index f285ca3c104400eaed851b8f87190785dd05c165..6e875a279146788650a8a6e3a71ade6abc9e8b79 100644
--- a/src/share/classes/sun/management/ManagementFactoryHelper.java
+++ b/src/share/classes/sun/management/ManagementFactoryHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ package sun.management;
import java.lang.management.*;
+import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
@@ -42,7 +43,9 @@ import sun.util.logging.LoggingSupport;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import com.sun.management.DiagnosticCommandMBean;
import com.sun.management.OSMBeanFactory;
import com.sun.management.HotSpotDiagnosticMXBean;
@@ -263,6 +266,7 @@ public class ManagementFactoryHelper {
private static HotspotThread hsThreadMBean = null;
private static HotspotCompilation hsCompileMBean = null;
private static HotspotMemory hsMemoryMBean = null;
+ private static DiagnosticCommandImpl hsDiagCommandMBean = null;
public static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() {
if (hsDiagMBean == null) {
@@ -311,6 +315,14 @@ public class ManagementFactoryHelper {
return hsMemoryMBean;
}
+ public static synchronized DiagnosticCommandMBean getDiagnosticCommandMBean() {
+ // Remote Diagnostic Commands may not be supported
+ if (hsDiagCommandMBean == null && jvm.isRemoteDiagnosticCommandsSupported()) {
+ hsDiagCommandMBean = new DiagnosticCommandImpl(jvm);
+ }
+ return hsDiagCommandMBean;
+ }
+
/**
* This method is for testing only.
*/
@@ -365,6 +377,18 @@ public class ManagementFactoryHelper {
private final static String HOTSPOT_THREAD_MBEAN_NAME =
"sun.management:type=HotspotThreading";
+ final static String HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME =
+ "com.sun.management:type=DiagnosticCommand";
+
+ public static HashMap getPlatformDynamicMBeans() {
+ HashMap 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
diff --git a/src/share/classes/sun/management/VMManagement.java b/src/share/classes/sun/management/VMManagement.java
index 50760baa398ad3bdce57adbe56bdaa5de3ec6832..a02f828ed163998d3e5152d7ae25f4bcd0237479 100644
--- a/src/share/classes/sun/management/VMManagement.java
+++ b/src/share/classes/sun/management/VMManagement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@ public interface VMManagement {
public boolean isThreadAllocatedMemorySupported();
public boolean isThreadAllocatedMemoryEnabled();
public boolean isGcNotificationSupported();
+ public boolean isRemoteDiagnosticCommandsSupported();
// Class Loading Subsystem
public long getTotalClassCount();
diff --git a/src/share/classes/sun/management/VMManagementImpl.java b/src/share/classes/sun/management/VMManagementImpl.java
index 88566ae99dbf545acb2ecdde2760daf2680e4752..46e0285e622aaa46b40bfa05d878744016d8f70a 100644
--- a/src/share/classes/sun/management/VMManagementImpl.java
+++ b/src/share/classes/sun/management/VMManagementImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@ class VMManagementImpl implements VMManagement {
private static boolean synchronizerUsageSupport;
private static boolean threadAllocatedMemorySupport;
private static boolean gcNotificationSupport;
+ private static boolean remoteDiagnosticCommandsSupport;
static {
@@ -106,6 +107,10 @@ class VMManagementImpl implements VMManagement {
return gcNotificationSupport;
}
+ public boolean isRemoteDiagnosticCommandsSupported() {
+ return remoteDiagnosticCommandsSupport;
+ }
+
public native boolean isThreadContentionMonitoringEnabled();
public native boolean isThreadCpuTimeEnabled();
public native boolean isThreadAllocatedMemoryEnabled();
diff --git a/src/share/javavm/export/jmm.h b/src/share/javavm/export/jmm.h
index e4b858c81874b4b60e893313d9fe96cf5e16d0ef..e017e5a02c78431dcc5e64add7d7f64f4549f786 100644
--- a/src/share/javavm/export/jmm.h
+++ b/src/share/javavm/export/jmm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,8 @@ enum {
JMM_VERSION_1_1 = 0x20010100, // JDK 6
JMM_VERSION_1_2 = 0x20010200, // JDK 7
JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA
- JMM_VERSION = 0x20010202
+ JMM_VERSION_1_2_2 = 0x20010202,
+ JMM_VERSION = 0x20010203
};
typedef struct {
@@ -62,7 +63,8 @@ typedef struct {
unsigned int isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1;
unsigned int isThreadAllocatedMemorySupported : 1;
- unsigned int : 23;
+ unsigned int isRemoteDiagnosticCommandsSupported : 1;
+ unsigned int : 22;
} jmmOptionalSupport;
typedef enum {
@@ -190,21 +192,27 @@ typedef struct {
} jmmGCStat;
typedef struct {
- const char* name;
- const char* description;
- const char* impact;
- int num_arguments;
- jboolean enabled;
+ const char* name; /* Name of the diagnostic command */
+ const char* description; /* Short description */
+ const char* impact; /* Impact on the JVM */
+ const char* permission_class; /* Class name of the required permission if any */
+ const char* permission_name; /* Permission name of the required permission if any */
+ const char* permission_action; /* Action name of the required permission if any*/
+ int num_arguments; /* Number of supported options or arguments */
+ jboolean enabled; /* True if the diagnostic command can be invoked, false otherwise*/
} dcmdInfo;
typedef struct {
- const char* name;
- const char* description;
- const char* type;
- const char* default_string;
- jboolean mandatory;
- jboolean option;
- int position;
+ const char* name; /* Option/Argument name*/
+ const char* description; /* Short description */
+ const char* type; /* Type: STRING, BOOLEAN, etc. */
+ const char* default_string; /* Default value in a parsable string */
+ jboolean mandatory; /* True if the option/argument is mandatory */
+ jboolean option; /* True if it is an option, false if it is an argument */
+ /* (see diagnosticFramework.hpp for option/argument definitions) */
+ jboolean multiple; /* True is the option can be specified several time */
+ int position; /* Expected position for this argument (this field is */
+ /* meaningless for options) */
} dcmdArgInfo;
typedef struct jmmInterface_1_ {
@@ -327,6 +335,9 @@ typedef struct jmmInterface_1_ {
jstring (JNICALL *ExecuteDiagnosticCommand)
(JNIEnv *env,
jstring command);
+ void (JNICALL *SetDiagnosticFrameworkNotificationEnabled)
+ (JNIEnv *env,
+ jboolean enabled);
} JmmInterface;
#ifdef __cplusplus
diff --git a/src/share/native/sun/management/DiagnosticCommandImpl.c b/src/share/native/sun/management/DiagnosticCommandImpl.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f601ed55a772ffabec4ea0e3d7a4c34472cc376
--- /dev/null
+++ b/src/share/native/sun/management/DiagnosticCommandImpl.c
@@ -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
+#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; iNewStringUTF(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; iGetObjectArrayElement(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);
+}
diff --git a/src/share/native/sun/management/VMManagementImpl.c b/src/share/native/sun/management/VMManagementImpl.c
index 1deb7c8c8cac0ffb42931caf5aaa758b324d8360..27784e5dd62bdc8cba9de3d84a15b08e765ae581 100644
--- a/src/share/native/sun/management/VMManagementImpl.c
+++ b/src/share/native/sun/management/VMManagementImpl.c
@@ -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
+#include
#include "jvm.h"
#include "management.h"
#include "sun_management_VMManagementImpl.h"
@@ -96,6 +97,9 @@ Java_sun_management_VMManagementImpl_initOptionalSupportFields
value = mos.isThreadAllocatedMemorySupported;
setStaticBooleanField(env, cls, "threadAllocatedMemorySupport", value);
+ value = mos.isRemoteDiagnosticCommandsSupported;
+ setStaticBooleanField(env, cls, "remoteDiagnosticCommandsSupport", value);
+
if ((jmm_version > JMM_VERSION_1_2) ||
(jmm_version == JMM_VERSION_1_2 && ((jmm_version&0xFF) >= 1))) {
setStaticBooleanField(env, cls, "gcNotificationSupport", JNI_TRUE);
diff --git a/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..91f30b0376c293c31814dde371e6e386652af5d2
--- /dev/null
+++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanDoubleInvocationTest.java
@@ -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");
+ }
+}
diff --git a/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanInvocationTest.java b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanInvocationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..02132c37e5dc03eb2caa67760d81f884f30968ab
--- /dev/null
+++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanInvocationTest.java
@@ -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");
+ }
+}
diff --git a/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanPermissionsTest.java b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanPermissionsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3499897dd9f996d53c9aaaffc1a5045e8e6c9fe0
--- /dev/null
+++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanPermissionsTest.java
@@ -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 grantedPermissions;
+
+ public CustomSecurityManager() {
+ grantedPermissions = new HashSet();
+ }
+
+ public final void grantPermission(final Permission perm) {
+ grantedPermissions.add(perm);
+ }
+
+ public final void denyPermission(final Permission perm) {
+ Iterator 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");
+ }
+}
diff --git a/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTest.java b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..10ce4240402f113b8078166920d8221a7ad6385a
--- /dev/null
+++ b/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTest.java
@@ -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 excludeList = new HashSet<>(
+ Arrays.asList("com.sun.management:type=DiagnosticCommand"));
+
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
@@ -92,6 +96,10 @@ public class MXBeanBehavior {
by generic MXBean tests.
*/
private static void test(MBeanServer mbs, ObjectName name) throws Exception {
+ if(excludeList.contains(name.getCanonicalName())) {
+ // Skipping not MXBean objects.
+ return;
+ }
System.out.println("Testing: " + name);
MBeanInfo mbi = mbs.getMBeanInfo(name);
diff --git a/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java b/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java
index b7d9b111f6be4cc98aedc47274d3826f414ddc83..00f3768efe622a8d638841ed63ce36bbf8decb71 100644
--- a/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java
+++ b/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,8 @@ import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.HashSet;
import javax.management.MBeanServer;
import javax.management.MBeanServerBuilder;
import javax.management.MBeanServerDelegate;
@@ -81,6 +83,9 @@ public class MBeanServerMXBeanUnsupportedTest {
public static class MBeanServerForwarderInvocationHandler
implements InvocationHandler {
+ public static final HashSet excludeList = new HashSet(
+ Arrays.asList("com.sun.management:type=DiagnosticCommand"));
+
public static MBeanServerForwarder newProxyInstance() {
final InvocationHandler handler =
@@ -126,15 +131,17 @@ public class MBeanServerMXBeanUnsupportedTest {
if (domain.equals("java.lang") ||
domain.equals("java.util.logging") ||
domain.equals("com.sun.management")) {
- String mxbean = (String)
- mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean");
- if (mxbean == null || !mxbean.equals("true")) {
- throw new RuntimeException(
+ if(!excludeList.contains(name.getCanonicalName())) {
+ String mxbean = (String)
+ mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean");
+ if (mxbean == null || !mxbean.equals("true")) {
+ throw new RuntimeException(
"Platform MBeans must be MXBeans!");
- }
- if (!(mbean instanceof StandardMBean)) {
- throw new RuntimeException(
+ }
+ if (!(mbean instanceof StandardMBean)) {
+ throw new RuntimeException(
"MXBeans must be wrapped in StandardMBean!");
+ }
}
}
return result;