--- old/make/java/management/Exportedfiles.gmk Mon Dec 17 10:38:16 2012 +++ new/make/java/management/Exportedfiles.gmk Mon Dec 17 10:38:16 2012 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2012, 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 \ --- old/make/java/management/FILES_c.gmk Mon Dec 17 10:38:18 2012 +++ new/make/java/management/FILES_c.gmk Mon Dec 17 10:38:17 2012 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2012, 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 \ --- old/make/java/management/mapfile-vers Mon Dec 17 10:38:20 2012 +++ new/make/java/management/mapfile-vers Mon Dec 17 10:38:19 2012 @@ -39,6 +39,7 @@ Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize; Java_com_sun_management_UnixOperatingSystem_initialize; Java_sun_management_ClassLoadingImpl_setVerboseClass; + Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled; Java_sun_management_FileSystemImpl_isAccessUserOnly0; Java_sun_management_Flag_getAllFlagNames; Java_sun_management_Flag_getFlags; @@ -85,11 +86,14 @@ Java_sun_management_ThreadImpl_setThreadContentionMonitoringEnabled0; Java_sun_management_ThreadImpl_setThreadCpuTimeEnabled0; Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0; + Java_sun_management_VMManagementImpl_executeDiagnosticCommand; Java_sun_management_VMManagementImpl_getAvailableProcessors; Java_sun_management_VMManagementImpl_getClassInitializationTime; Java_sun_management_VMManagementImpl_getClassLoadingTime; Java_sun_management_VMManagementImpl_getClassVerificationTime; Java_sun_management_VMManagementImpl_getDaemonThreadCount; + Java_sun_management_VMManagementImpl_getDiagnosticCommands; + Java_sun_management_VMManagementImpl_getDiagnosticCommandInfo; Java_sun_management_VMManagementImpl_getInitializedClassCount; Java_sun_management_VMManagementImpl_getLiveThreadCount; Java_sun_management_VMManagementImpl_getLoadedClassSize; --- old/src/share/classes/java/lang/management/ManagementFactory.java Mon Dec 17 10:38:21 2012 +++ new/src/share/classes/java/lang/management/ManagementFactory.java Mon Dec 17 10:38:21 2012 @@ -482,6 +482,12 @@ } } } + List dynamicPMOList = ManagementFactoryHelper.getPlatformDynamicMBeans(); + for (PlatformManagedObject o : dynamicPMOList) { + if (!platformMBeanServer.isRegistered(o.getObjectName())) { + addMXBean(platformMBeanServer, o); + } + } } return platformMBeanServer; } --- old/src/share/classes/sun/management/ManagementFactoryHelper.java Mon Dec 17 10:38:23 2012 +++ new/src/share/classes/sun/management/ManagementFactoryHelper.java Mon Dec 17 10:38:22 2012 @@ -43,6 +43,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import com.sun.management.DiagnosticCommandMBean; import com.sun.management.OSMBeanFactory; import com.sun.management.HotSpotDiagnosticMXBean; @@ -263,6 +264,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 +313,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 +375,14 @@ private final static String HOTSPOT_THREAD_MBEAN_NAME = "sun.management:type=HotspotThreading"; + public static List getPlatformDynamicMBeans() { + List list = new ArrayList<>(); + if(getDiagnosticCommandMBean() != null) { + list.add(getDiagnosticCommandMBean()); + } + return list; + } + static void registerInternalMBeans(MBeanServer mbs) { // register all internal MBeans if not registered // No exception is thrown if a MBean with that object name --- old/src/share/classes/sun/management/VMManagement.java Mon Dec 17 10:38:25 2012 +++ new/src/share/classes/sun/management/VMManagement.java Mon Dec 17 10:38:24 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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(); @@ -103,4 +104,9 @@ // Performance counter support public List getInternalCounters(String pattern); + + // Diagnostic Commands support + public String[] getDiagnosticCommands(); + public DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands); + public String executeDiagnosticCommand(String command); } --- old/src/share/classes/sun/management/VMManagementImpl.java Mon Dec 17 10:38:27 2012 +++ new/src/share/classes/sun/management/VMManagementImpl.java Mon Dec 17 10:38:26 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 { @@ -105,6 +106,10 @@ public boolean isGcNotificationSupported() { return gcNotificationSupport; } + + public boolean isRemoteDiagnosticCommandsSupported() { + return remoteDiagnosticCommandsSupport; + } public native boolean isThreadContentionMonitoringEnabled(); public native boolean isThreadCpuTimeEnabled(); @@ -268,4 +273,11 @@ return Collections.emptyList(); } } + + @Override + public native String[] getDiagnosticCommands(); + @Override + public native DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands); + @Override + public native String executeDiagnosticCommand(String command); } --- old/src/share/javavm/export/jmm.h Mon Dec 17 10:38:28 2012 +++ new/src/share/javavm/export/jmm.h Mon Dec 17 10:38:28 2012 @@ -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,28 @@ } 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 +336,9 @@ jstring (JNICALL *ExecuteDiagnosticCommand) (JNIEnv *env, jstring command); + void (JNICALL *SetDiagnosticFrameworkNotificationEnabled) + (JNIEnv *env, + jboolean enabled); } JmmInterface; #ifdef __cplusplus --- old/src/share/native/sun/management/VMManagementImpl.c Mon Dec 17 10:38:30 2012 +++ new/src/share/native/sun/management/VMManagementImpl.c Mon Dec 17 10:38:29 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ 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); @@ -320,4 +324,154 @@ { return jmm_interface->GetLongAttribute(env, NULL, JMM_CLASS_VERIFY_TOTAL_TIME_MS); +} + +JNIEXPORT jobjectArray JNICALL +Java_sun_management_VMManagementImpl_getDiagnosticCommands + (JNIEnv *env, jobject dummy) +{ + jmmOptionalSupport mos; + jint ret = jmm_interface->GetOptionalSupport(env, &mos); + jboolean rdcmd_support = mos.isRemoteDiagnosticCommandsSupported; + if (rdcmd_support) { + return jmm_interface->GetDiagnosticCommands(env); + } + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "JMX interface to diagnostic commands is not supported by this VM"); +} + +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 the diagnostic command + * passed in argument is not supported by the JVM + */ +JNIEXPORT jobjectArray JNICALL +Java_sun_management_VMManagementImpl_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); + jboolean rdcmd_support = mos.isRemoteDiagnosticCommandsSupported; + jsize num_commands; + dcmdInfo* dcmd_info_array; + + if (rdcmd_support) { + 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; + } + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "JMX interface to diagnostic commands is not supported by this VM"); +} + +/* Throws IllegalArgumentException if the diagnostic command + * passed in argument is not supported by the JVM + */ +JNIEXPORT jstring JNICALL +Java_sun_management_VMManagementImpl_executeDiagnosticCommand +(JNIEnv *env, jobject dummy, jstring command) { + jmmOptionalSupport mos; + jint ret = jmm_interface->GetOptionalSupport(env, &mos); + jboolean rdcmd_support = mos.isRemoteDiagnosticCommandsSupported; + if (rdcmd_support) { + return jmm_interface->ExecuteDiagnosticCommand(env, command); + } + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "JMX interface to diagnostic commands is not supported by this VM"); } --- old/test/java/lang/management/MXBean/MXBeanBehavior.java Mon Dec 17 10:38:32 2012 +++ new/test/java/lang/management/MXBean/MXBeanBehavior.java Mon Dec 17 10:38:31 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012 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,9 @@ import javax.management.*; public class MXBeanBehavior { + public static final HashSet dynamicMBeanList = new HashSet( + Arrays.asList("com.sun.management:type=DiagnosticCommand")); + public static void main(String[] args) throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); @@ -99,8 +102,13 @@ Object[] values = mbid.getFieldValues("immutableInfo", "interfaceClassName", "mxbean"); - checkEqual(values[0], "true", name + " immutableInfo field"); - checkEqual(values[2], "true", name + " mxbean field"); + if(dynamicMBeanList.contains(name.getCanonicalName())) { + checkEqual(values[0], "false", name + " immutableInfo field"); + checkEqual(values[2], "false", name + " mxbean field"); + } else { + checkEqual(values[0], "true", name + " immutableInfo field"); + checkEqual(values[2], "true", name + " mxbean field"); + } String interfaceClassName = (String) values[1]; if (!mbs.isInstanceOf(name, interfaceClassName)) { throw new RuntimeException(name + " not instance of " + --- old/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java Mon Dec 17 10:38:33 2012 +++ new/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java Mon Dec 17 10:38:33 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2012 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 excludeList = new HashSet( + Arrays.asList("com.sun.management:type=DiagnosticCommand")); + public static MBeanServerForwarder newProxyInstance() { final InvocationHandler handler = @@ -126,16 +131,18 @@ 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( - "Platform MBeans must be MXBeans!"); - } - if (!(mbean instanceof StandardMBean)) { - 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( "MXBeans must be wrapped in StandardMBean!"); - } + } + } } return result; } --- /dev/null Mon Dec 17 10:38:35 2012 +++ new/src/share/classes/com/sun/management/DiagnosticCommandMBean.java Mon Dec 17 10:38:34 2012 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2012, 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; + +/** + * Diagnostic Commands interface for the HotSpot Virtual Machine. + * + *

The diagnostic command MBean is registered to the platform MBeanServer + * as are other platform MBeans. + * + *

The ObjectName for uniquely identifying the diagnostic + * MBean within an MBeanServer is: + *

+ * com.sun.management:type=DiagnosticCommand + *
+ * + * It can be obtained by calling the + * {@link PlatformManagedObject#getObjectName} method. + * + *

This MBean is an instance of DynamicMBean. Its content is generated at + * runtime and is subject to modifications during the lifetime of the + * Java virtual machine. + * + *

This MBean implements the DynamicMBean interface and + * the NotificationEmitter interface. + * + *

The dynamically defined part of the DiagnosticCommandMBean + * is made of a set of operations, one per diagnostic command + * available through the JMX API. Diagnostic commands names often include + * characters forbidden in Java method names (like dots). The generation of + * an operation name for a given diagnostic command is implementation dependent. + * The recommended way to transform diagnostic command name into a MBean + * operation name is described below: + *

    + *
  • 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
  • + *
+ * + *

Whatever algorithm is used to generated the operation name, the original + * diagnostic command name is always provided with the meta-data on the + * operation in a field named dcmd.name (see below). + * + *

All the operations associated with a diagnostic command return + * a String. + * + *

All the operations associated with a diagnostic command which + * doesn't support any option or argument have the following + * signature: + *

+ * ()Ljava/lang/String; + *
+ *

All the operations associated with a diagnostic command supporting + * at least one option or argument have the following signature: + *

+ * ([Ljava/lang/String;)Ljava/lang/String; + *
+ *

For these operations, all the options and arguments are passed into an + * array of String. 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 MBeanOperationInfo instance. Here's the values returned + * by this object: + *

    + *
  • getName() returns the operation name generated from the + * diagnostic command name
  • + *
  • getDescription() returns the diagnostic command description + * (the same as the one return in the 'help' command)
  • + *
  • getImpact() returns ACTION_INFO
  • + *
  • getReturnType() returns java.lang.String
  • + *
  • getDescriptor() returns a Descriptor instance (see below)
  • + *
+ *

The 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: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
NameTypeDescription
dcmd.nameStringThe original diagnostic command name (not the operation name)
dcmd.descriptionStringThe diagnostic command description
dcmd.helpStringThe full help message for this diagnostic command (same output as + * the one produced by the 'help' command)
dcmd.vmImpactStringThe 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.enabledbooleanTrue if the diagnostic command is enabled, false otherwise
dcmd.permissionClassStringSome 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 class name + * of this permission or null if no permission is required
dcmd.permissionNameStringThe fist argument of the permission required to execute this + * diagnostic command or null if no permission is required
dcmd.permissionActionStringThe 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.argumentsDescriptorA 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: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
NameTypeDescription
dcmd.arg.nameStringThe name of the parameter
dcmd.arg.typeStringThe 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.descriptionStringThe parameter description
dcmd.arg.isMandatorybooleanTrue if the parameter is mandatory, false otherwise
dcmd.arg.isOptionbooleanTrue if the parameter is an option, false if it is an argument
dcmd.arg.isMultiplebooleanTrue 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 DiagnosticCommandMBean emits + * a {@link Notification} with a {@linkplain Notification#getType() type} of + * {@code "jmx.mbean.info.changed"} and a {@linkplain + * Notification#getUserData() userData} that is the new {@code MBeanInfo}. + * + * @since 7u12 + */ +public interface DiagnosticCommandMBean extends DynamicMBean, + PlatformManagedObject { + +} --- /dev/null Mon Dec 17 10:38:37 2012 +++ new/src/share/classes/sun/management/DiagnosticCommandArgumentInfo.java Mon Dec 17 10:38:36 2012 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012, 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. + * + * @author Frederic Parain + * @since 7u6 + */ + +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 + */ + public String getName() { + return name; + } + + /** + * Returns the argument description. + * + * @return the argument description + */ + public String getDescription() { + return description; + } + + /** + * Returns the argument type. + * + * @return the argument type + */ + public 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. + */ + public 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 + */ + public 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 + */ + public 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 + */ + public 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. + */ + public int getPosition() { + return position; + } + + public 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 Mon Dec 17 10:38:38 2012 +++ new/src/share/classes/sun/management/DiagnosticCommandImpl.java Mon Dec 17 10:38:38 2012 @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2012, 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.*; + +public class DiagnosticCommandImpl extends NotificationEmitterSupport + implements DiagnosticCommandMBean { + + private VMManagement jvm; + private volatile Map wrappers; + + @Override + public Object getAttribute(String attribute) throws AttributeNotFoundException, + MBeanException, ReflectionException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void setAttribute(Attribute attribute) throws AttributeNotFoundException, + InvalidAttributeValueException, MBeanException, ReflectionException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public AttributeList getAttributes(String[] attributes) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public AttributeList setAttributes(AttributeList attributes) { + throw new UnsupportedOperationException("Not supported."); + } + + 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; + 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) { } + } + 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) { } + } + } catch (ClassNotFoundException ex) { } + if (permission == null) { + throw new InstantiationException("Unable to instantiate required permission"); + } + } + } + + public String execute(String[] args) { + if (permission != null) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(permission); + } + } + if(args == null) { + return jvm.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; + try { + String[] command = jvm.getDiagnosticCommands(); + DiagnosticCommandInfo[] info = jvm.getDiagnosticCommandInfo(command); + wrappersmap = new HashMap<>(); + for (int i = 0; i < command.length; i++) { + String name = transform(command[i]); + try { + wrappersmap.put(name, + new Wrapper(name, command[i], info[i])); + } 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 + } + } + MBeanParameterInfo stringArgInfo[] = new MBeanParameterInfo[]{ + new MBeanParameterInfo("arguments", "[Ljava.lang.String;", + "Array of Diagnostic Commands Arguments and Options") + }; + for (Wrapper w : wrappersmap.values()) { + if (w.info.getArgumentsInfo() == null || w.info.getArgumentsInfo().isEmpty()) { + operations.add(new MBeanOperationInfo( + w.name, + w.info.getDescription(), + null, + "java.lang.String", + MBeanOperationInfo.ACTION_INFO, + commandDescriptor(w))); + } else { + operations.add(new MBeanOperationInfo( + w.name, + w.info.getDescription(), + stringArgInfo, + "java.lang.String", + MBeanOperationInfo.ACTION_INFO, + commandDescriptor(w))); + } + } + } 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 { + 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].compareTo("[Ljava.lang.String;") == 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.permissionCame", 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", jvm.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()); + } + 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; + } + Notification notif = new Notification("jmx.mbean.info.changed", + getObjectName(), + 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); + + @Override + public ObjectName getObjectName() { + return Util.newObjectName("com.sun.management:type=DiagnosticCommand"); + } +} --- /dev/null Mon Dec 17 10:38:40 2012 +++ new/src/share/classes/sun/management/DiagnosticCommandInfo.java Mon Dec 17 10:38:39 2012 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2012, 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. + */ + +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 + */ + public String getName() { + return name; + } + + /** + * Returns the diagnostic command description. + * + * @return the diagnostic command description + */ + public 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 + */ + public 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 + */ + public 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 + */ + public 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 + */ + public 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 + */ + public 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 + */ + public List getArgumentsInfo() { + return arguments; + } + + public 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; + } +} --- /dev/null Mon Dec 17 10:38:42 2012 +++ new/src/share/native/sun/management/DiagnosticCommandImpl.c Mon Dec 17 10:38:41 2012 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 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"); + } +} --- /dev/null Mon Dec 17 10:38:43 2012 +++ new/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanInvocationTest.java Mon Dec 17 10:38:42 2012 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, 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=8123 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:8123/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 = {"[Ljava/lang/String;"}; + String result = (String) mbs.invoke(name, "help", dcmdArgs, signature); + System.out.println(result); + } catch (InstanceNotFoundException|IntrospectionException|ReflectionException + |MalformedObjectNameException|MBeanException|IOException ex) { + Logger.getLogger(DcmdMBeanTest.class.getName()).log(Level.SEVERE, null, ex); + } + } +} + --- /dev/null Mon Dec 17 10:38:45 2012 +++ new/test/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTest.java Mon Dec 17 10:38:44 2012 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012, 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=8123 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:8123/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