--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri May 03 05:17:15 2013 -0700
@@ -517,13 +517,18 @@
template(sun_management_ManagementFactory, "sun/management/ManagementFactory") \
template(sun_management_Sensor, "sun/management/Sensor") \
template(sun_management_Agent, "sun/management/Agent") \
+ template(sun_management_DiagnosticCommandImpl, "sun/management/DiagnosticCommandImpl") \
template(sun_management_GarbageCollectorImpl, "sun/management/GarbageCollectorImpl") \
+ template(sun_management_ManagementFactoryHelper, "sun/management/ManagementFactoryHelper") \
+ template(getDiagnosticCommandMBean_name, "getDiagnosticCommandMBean") \
+ template(getDiagnosticCommandMBean_signature, "()Lcom/sun/management/DiagnosticCommandMBean;") \
template(getGcInfoBuilder_name, "getGcInfoBuilder") \
template(getGcInfoBuilder_signature, "()Lsun/management/GcInfoBuilder;") \
template(com_sun_management_GcInfo, "com/sun/management/GcInfo") \
template(com_sun_management_GcInfo_constructor_signature, "(Lsun/management/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V") \
template(createGCNotification_name, "createGCNotification") \
template(createGCNotification_signature, "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/sun/management/GcInfo;)V") \
+ template(createDiagnosticFrameworkNotification_name, "createDiagnosticFrameworkNotification") \
template(createMemoryPoolMBean_name, "createMemoryPoolMBean") \
template(createMemoryManagerMBean_name, "createMemoryManagerMBean") \
template(createGarbageCollectorMBean_name, "createGarbageCollectorMBean") \
--- a/hotspot/src/share/vm/runtime/serviceThread.cpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/runtime/serviceThread.cpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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,8 @@
#include "runtime/mutexLocker.hpp"
#include "prims/jvmtiImpl.hpp"
#include "services/gcNotifier.hpp"
+#include "services/diagnosticArgument.hpp"
+#include "services/diagnosticFramework.hpp"
ServiceThread* ServiceThread::_instance = NULL;
@@ -83,6 +85,7 @@
bool sensors_changed = false;
bool has_jvmti_events = false;
bool has_gc_notification_event = false;
+ bool has_dcmd_notification_event = false;
JvmtiDeferredEvent jvmti_event;
{
// Need state transition ThreadBlockInVM so that this thread
@@ -98,7 +101,8 @@
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
while (!(sensors_changed = LowMemoryDetector::has_pending_requests()) &&
!(has_jvmti_events = JvmtiDeferredEventQueue::has_events()) &&
- !(has_gc_notification_event = GCNotifier::has_event())) {
+ !(has_gc_notification_event = GCNotifier::has_event()) &&
+ !(has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification())) {
// wait until one of the sensors has pending requests, or there is a
// pending JVMTI event or JMX GC notification to post
Service_lock->wait(Mutex::_no_safepoint_check_flag);
@@ -120,6 +124,10 @@
if(has_gc_notification_event) {
GCNotifier::sendNotification(CHECK);
}
+
+ if(has_dcmd_notification_event) {
+ DCmdFactory::send_notification(CHECK);
+ }
}
}
--- a/hotspot/src/share/vm/services/attachListener.cpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/attachListener.cpp Fri May 03 05:17:15 2013 -0700
@@ -157,7 +157,7 @@
Thread* THREAD = Thread::current();
// All the supplied jcmd arguments are stored as a single
// string (op->arg(0)). This is parsed by the Dcmd framework.
- DCmd::parse_and_execute(out, op->arg(0), ' ', THREAD);
+ DCmd::parse_and_execute(DCmd_Source_AttachAPI, out, op->arg(0), ' ', THREAD);
if (HAS_PENDING_EXCEPTION) {
java_lang_Throwable::print(PENDING_EXCEPTION, out);
out->cr();
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri May 03 05:17:15 2013 -0700
@@ -34,26 +34,33 @@
void DCmdRegistrant::register_dcmds(){
// Registration of the diagnostic commands
- // First boolean argument specifies if the command is enabled
- // Second boolean argument specifies if the command is hidden
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(true, false));
+ // First argument specifies which interfaces will export the command
+ // Second argument specifies if the command is enabled
+ // Third argument specifies if the command is hidden
+ uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI
+ | DCmd_Source_MBean;
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));
#if INCLUDE_SERVICES // Heap dumping/inspection supported
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
#endif // INCLUDE_SERVICES
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false));
- //Enhanced JMX Agent Support
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(true,false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(true,false));
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(true,false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
+
+ // Enhanced JMX Agent Support
+ // These commands won't be exported via the DiagnosticCommandMBean until an
+ // appropriate permission is created for them
+ uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI;
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(jmx_agent_export_flags, true,false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(jmx_agent_export_flags, true,false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags, true,false));
}
@@ -72,29 +79,37 @@
_dcmdparser.add_dcmd_argument(&_cmd);
};
-void HelpDCmd::execute(TRAPS) {
+void HelpDCmd::execute(DCmdSource source, TRAPS) {
if (_all.value()) {
- GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list();
+ GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(source);
for (int i = 0; i < cmd_list->length(); i++) {
- DCmdFactory* factory = DCmdFactory::factory(cmd_list->at(i),
+ DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
strlen(cmd_list->at(i)));
- if (!factory->is_hidden()) {
- output()->print_cr("%s%s", factory->name(),
- factory->is_enabled() ? "" : " [disabled]");
- output()->print_cr("\t%s", factory->description());
- output()->cr();
- }
+ output()->print_cr("%s%s", factory->name(),
+ factory->is_enabled() ? "" : " [disabled]");
+ output()->print_cr("\t%s", factory->description());
+ output()->cr();
factory = factory->next();
}
} else if (_cmd.has_value()) {
DCmd* cmd = NULL;
- DCmdFactory* factory = DCmdFactory::factory(_cmd.value(),
+ DCmdFactory* factory = DCmdFactory::factory(source, _cmd.value(),
strlen(_cmd.value()));
if (factory != NULL) {
output()->print_cr("%s%s", factory->name(),
factory->is_enabled() ? "" : " [disabled]");
output()->print_cr(factory->description());
output()->print_cr("\nImpact: %s", factory->impact());
+ JavaPermission p = factory->permission();
+ if(p._class != NULL) {
+ if(p._action != NULL) {
+ output()->print_cr("\nPermission: %s(%s, %s)",
+ p._class, p._name == NULL ? "null" : p._name, p._action);
+ } else {
+ output()->print_cr("\nPermission: %s(%s)",
+ p._class, p._name == NULL ? "null" : p._name);
+ }
+ }
output()->cr();
cmd = factory->create_resource_instance(output());
if (cmd != NULL) {
@@ -106,14 +121,12 @@
}
} else {
output()->print_cr("The following commands are available:");
- GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list();
+ GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list(source);
for (int i = 0; i < cmd_list->length(); i++) {
- DCmdFactory* factory = DCmdFactory::factory(cmd_list->at(i),
+ DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
strlen(cmd_list->at(i)));
- if (!factory->is_hidden()) {
- output()->print_cr("%s%s", factory->name(),
- factory->is_enabled() ? "" : " [disabled]");
- }
+ output()->print_cr("%s%s", factory->name(),
+ factory->is_enabled() ? "" : " [disabled]");
factory = factory->_next;
}
output()->print_cr("\nFor more information about a specific command use 'help <command>'.");
@@ -131,7 +144,7 @@
}
}
-void VersionDCmd::execute(TRAPS) {
+void VersionDCmd::execute(DCmdSource source, TRAPS) {
output()->print_cr("%s version %s", Abstract_VM_Version::vm_name(),
Abstract_VM_Version::vm_release());
JDK_Version jdk_version = JDK_Version::current();
@@ -150,7 +163,7 @@
_dcmdparser.add_dcmd_option(&_all);
}
-void PrintVMFlagsDCmd::execute(TRAPS) {
+void PrintVMFlagsDCmd::execute(DCmdSource source, TRAPS) {
if (_all.value()) {
CommandLineFlags::printFlags(output(), true);
} else {
@@ -169,7 +182,7 @@
}
}
-void PrintSystemPropertiesDCmd::execute(TRAPS) {
+void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
// load sun.misc.VMSupport
Symbol* klass = vmSymbols::sun_misc_VMSupport();
Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK);
@@ -219,7 +232,7 @@
_dcmdparser.add_dcmd_option(&_date);
}
-void VMUptimeDCmd::execute(TRAPS) {
+void VMUptimeDCmd::execute(DCmdSource source, TRAPS) {
if (_date.value()) {
output()->date_stamp(true, "", ": ");
}
@@ -239,11 +252,15 @@
}
}
-void SystemGCDCmd::execute(TRAPS) {
- Universe::heap()->collect(GCCause::_java_lang_system_gc);
+void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
+ if (!DisableExplicitGC) {
+ Universe::heap()->collect(GCCause::_java_lang_system_gc);
+ } else {
+ output()->print_cr("Explicit GC is disabled, no GC has been performed.");
+ }
}
-void RunFinalizationDCmd::execute(TRAPS) {
+void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(),
true, CHECK);
instanceKlassHandle klass(THREAD, k);
@@ -263,7 +280,7 @@
_dcmdparser.add_dcmd_argument(&_filename);
}
-void HeapDumpDCmd::execute(TRAPS) {
+void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
// Request a full GC before heap dump if _all is false
// This helps reduces the amount of unreachable objects in the dump
// and makes it easier to browse.
@@ -301,7 +318,7 @@
_dcmdparser.add_dcmd_option(&_all);
}
-void ClassHistogramDCmd::execute(TRAPS) {
+void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {
VM_GC_HeapInspection heapop(output(),
!_all.value() /* request full gc if false */,
true /* need_prologue */);
@@ -337,7 +354,7 @@
_dcmdparser.add_dcmd_argument(&_columns);
}
-void ClassStatsDCmd::execute(TRAPS) {
+void ClassStatsDCmd::execute(DCmdSource source, TRAPS) {
if (!UnlockDiagnosticVMOptions) {
output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions");
return;
@@ -384,7 +401,7 @@
_dcmdparser.add_dcmd_option(&_locks);
}
-void ThreadDumpDCmd::execute(TRAPS) {
+void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) {
// thread stacks
VM_PrintThreads op1(output(), _locks.value());
VMThread::execute(&op1);
@@ -526,7 +543,8 @@
}
}
-void JMXStartRemoteDCmd::execute(TRAPS) {
+
+void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
@@ -593,7 +611,7 @@
// do nothing
}
-void JMXStartLocalDCmd::execute(TRAPS) {
+void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
@@ -611,7 +629,7 @@
}
-void JMXStopRemoteDCmd::execute(TRAPS) {
+void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Fri May 03 05:17:15 2013 -0700
@@ -51,7 +51,7 @@
}
static const char* impact() { return "Low"; }
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
class VersionDCmd : public DCmd {
@@ -62,8 +62,13 @@
return "Print JVM version information.";
}
static const char* impact() { return "Low"; }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.util.PropertyPermission",
+ "java.vm.version", "read"};
+ return p;
+ }
static int num_arguments() { return 0; }
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
class CommandLineDCmd : public DCmd {
@@ -74,8 +79,13 @@
return "Print the command line used to start this VM instance.";
}
static const char* impact() { return "Low"; }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
static int num_arguments() { return 0; }
- virtual void execute(TRAPS) {
+ virtual void execute(DCmdSource source, TRAPS) {
Arguments::print_on(_output);
}
};
@@ -91,8 +101,13 @@
static const char* impact() {
return "Low";
}
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.util.PropertyPermission",
+ "*", "read"};
+ return p;
+ }
static int num_arguments() { return 0; }
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
// See also: print_flag in attachListener.cpp
@@ -108,8 +123,13 @@
static const char* impact() {
return "Low";
}
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
class VMUptimeDCmd : public DCmdWithParser {
@@ -125,7 +145,7 @@
return "Low";
}
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
class SystemGCDCmd : public DCmd {
@@ -139,7 +159,7 @@
return "Medium: Depends on Java heap size and content.";
}
static int num_arguments() { return 0; }
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
class RunFinalizationDCmd : public DCmd {
@@ -153,7 +173,7 @@
return "Medium: Depends on Java content.";
}
static int num_arguments() { return 0; }
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
#if INCLUDE_SERVICES // Heap dumping supported
@@ -174,8 +194,13 @@
return "High: Depends on Java heap size and content. "
"Request a full GC unless the '-all' option is specified.";
}
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
#endif // INCLUDE_SERVICES
@@ -194,8 +219,13 @@
static const char* impact() {
return "High: Depends on Java heap size and content.";
}
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
class ClassStatsDCmd : public DCmdWithParser {
@@ -216,7 +246,7 @@
return "High: Depends on Java heap size and content.";
}
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
// See also: thread_dump in attachListener.cpp
@@ -232,8 +262,13 @@
static const char* impact() {
return "Medium: Depends on the number of threads.";
}
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
// Enhanced JMX Agent support
@@ -281,7 +316,7 @@
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
@@ -302,7 +337,7 @@
return "Start local management agent.";
}
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
@@ -321,7 +356,7 @@
return "Stop remote management agent.";
}
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/services/diagnosticFramework.cpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/diagnosticFramework.cpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -359,7 +359,7 @@
while (arg != NULL) {
array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
arg->type(), arg->default_string(), arg->is_mandatory(),
- false, idx));
+ false, arg->allow_multiple(), idx));
idx++;
arg = arg->next();
}
@@ -367,32 +367,42 @@
while (arg != NULL) {
array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
arg->type(), arg->default_string(), arg->is_mandatory(),
- true));
+ true, arg->allow_multiple()));
arg = arg->next();
}
return array;
}
DCmdFactory* DCmdFactory::_DCmdFactoryList = NULL;
+bool DCmdFactory::_has_pending_jmx_notification = false;
-void DCmd::parse_and_execute(outputStream* out, const char* cmdline,
- char delim, TRAPS) {
+void DCmd::parse_and_execute(DCmdSource source, outputStream* out,
+ const char* cmdline, char delim, TRAPS) {
if (cmdline == NULL) return; // Nothing to do!
DCmdIter iter(cmdline, '\n');
+ int count = 0;
while (iter.has_next()) {
+ if(source == DCmd_Source_MBean && count > 0) {
+ // When diagnostic commands are invoked via JMX, each command line
+ // must contains one and only one command because of the Permission
+ // checks performed by the DiagnosticCommandMBean
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "Invalid syntax");
+ }
CmdLine line = iter.next();
if (line.is_stop()) {
break;
}
if (line.is_executable()) {
- DCmd* command = DCmdFactory::create_local_DCmd(line, out, CHECK);
+ DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK);
assert(command != NULL, "command error must be handled before this line");
DCmdMark mark(command);
command->parse(&line, delim, CHECK);
- command->execute(CHECK);
+ command->execute(source, CHECK);
}
+ count++;
}
}
@@ -420,15 +430,78 @@
return _dcmdparser.argument_info_array();
}
-Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true);
+void DCmdFactory::push_jmx_notification_request() {
+ MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ _has_pending_jmx_notification = true;
+ Service_lock->notify_all();
+}
+
+void DCmdFactory::send_notification(TRAPS) {
+ DCmdFactory::send_notification_internal(THREAD);
+ // Clearing pending exception to avoid premature termination of
+ // the service thread
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ }
+}
+void DCmdFactory::send_notification_internal(TRAPS) {
+ ResourceMark rm(THREAD);
+ HandleMark hm(THREAD);
+ bool notif = false;
+ {
+ MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ notif = _has_pending_jmx_notification;
+ _has_pending_jmx_notification = false;
+ }
+ if (notif) {
+
+ Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK);
+ instanceKlassHandle mgmt_factory_helper_klass(THREAD, k);
-DCmdFactory* DCmdFactory::factory(const char* name, size_t len) {
+ JavaValue result(T_OBJECT);
+ JavaCalls::call_static(&result,
+ mgmt_factory_helper_klass,
+ vmSymbols::getDiagnosticCommandMBean_name(),
+ vmSymbols::getDiagnosticCommandMBean_signature(),
+ CHECK);
+
+ instanceOop m = (instanceOop) result.get_jobject();
+ instanceHandle dcmd_mbean_h(THREAD, m);
+
+ Klass* k2 = Management::sun_management_DiagnosticCommandImpl_klass(CHECK);
+ instanceKlassHandle dcmd_mbean_klass(THREAD, k2);
+
+ if (!dcmd_mbean_h->is_a(k2)) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "ManagementFactory.getDiagnosticCommandMBean didn't return a DiagnosticCommandMBean instance");
+ }
+
+ JavaValue result2(T_VOID);
+ JavaCallArguments args2(dcmd_mbean_h);
+
+ JavaCalls::call_virtual(&result2,
+ dcmd_mbean_klass,
+ vmSymbols::createDiagnosticFrameworkNotification_name(),
+ vmSymbols::void_method_signature(),
+ &args2,
+ CHECK);
+ }
+}
+
+Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true);
+bool DCmdFactory::_send_jmx_notification = false;
+
+DCmdFactory* DCmdFactory::factory(DCmdSource source, const char* name, size_t len) {
MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
DCmdFactory* factory = _DCmdFactoryList;
while (factory != NULL) {
if (strlen(factory->name()) == len &&
strncmp(name, factory->name(), len) == 0) {
- return factory;
+ if(factory->export_flags() & source) {
+ return factory;
+ } else {
+ return NULL;
+ }
}
factory = factory->_next;
}
@@ -439,11 +512,16 @@
MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
factory->_next = _DCmdFactoryList;
_DCmdFactoryList = factory;
+ if (_send_jmx_notification && !factory->_hidden
+ && (factory->_export_flags & DCmd_Source_MBean)) {
+ DCmdFactory::push_jmx_notification_request();
+ }
return 0; // Actually, there's no checks for duplicates
}
-DCmd* DCmdFactory::create_global_DCmd(CmdLine &line, outputStream* out, TRAPS) {
- DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len());
+DCmd* DCmdFactory::create_global_DCmd(DCmdSource source, CmdLine &line,
+ outputStream* out, TRAPS) {
+ DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
if (f != NULL) {
if (f->is_enabled()) {
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
@@ -455,8 +533,9 @@
"Unknown diagnostic command");
}
-DCmd* DCmdFactory::create_local_DCmd(CmdLine &line, outputStream* out, TRAPS) {
- DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len());
+DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line,
+ outputStream* out, TRAPS) {
+ DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
if (f != NULL) {
if (!f->is_enabled()) {
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
@@ -468,12 +547,12 @@
"Unknown diagnostic command");
}
-GrowableArray<const char*>* DCmdFactory::DCmd_list() {
+GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
GrowableArray<const char*>* array = new GrowableArray<const char*>();
DCmdFactory* factory = _DCmdFactoryList;
while (factory != NULL) {
- if (!factory->is_hidden()) {
+ if (!factory->is_hidden() && (factory->export_flags() & source)) {
array->append(factory->name());
}
factory = factory->next();
@@ -481,15 +560,16 @@
return array;
}
-GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list() {
+GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list(DCmdSource source ) {
MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
GrowableArray<DCmdInfo*>* array = new GrowableArray<DCmdInfo*>();
DCmdFactory* factory = _DCmdFactoryList;
while (factory != NULL) {
- if (!factory->is_hidden()) {
+ if (!factory->is_hidden() && (factory->export_flags() & source)) {
array->append(new DCmdInfo(factory->name(),
factory->description(), factory->impact(),
- factory->num_arguments(), factory->is_enabled()));
+ factory->permission(), factory->num_arguments(),
+ factory->is_enabled()));
}
factory = factory->next();
}
--- a/hotspot/src/share/vm/services/diagnosticFramework.hpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/diagnosticFramework.hpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -34,6 +34,22 @@
#include "utilities/ostream.hpp"
+enum DCmdSource {
+ DCmd_Source_Internal = 0x01U, // invocation from the JVM
+ DCmd_Source_AttachAPI = 0x02U, // invocation via the attachAPI
+ DCmd_Source_MBean = 0x04U // invocation via a MBean
+};
+
+// Warning: strings referenced by the JavaPermission struct are passed to
+// the native part of the JDK. Avoid use of dynamically allocated strings
+// that could be de-allocated before the JDK native code had time to
+// convert them into Java Strings.
+struct JavaPermission {
+ const char* _class;
+ const char* _name;
+ const char* _action;
+};
+
// CmdLine is the class used to handle a command line containing a single
// diagnostic command and its arguments. It provides methods to access the
// command name and the beginning of the arguments. The class is also
@@ -113,26 +129,30 @@
// used to export the description to the JMX interface of the framework.
class DCmdInfo : public ResourceObj {
protected:
- const char* _name;
- const char* _description;
- const char* _impact;
- int _num_arguments;
- bool _is_enabled;
+ const char* _name; /* Name of the diagnostic command */
+ const char* _description; /* Short description */
+ const char* _impact; /* Impact on the JVM */
+ JavaPermission _permission; /* Java Permission required to execute this command if any */
+ int _num_arguments; /* Number of supported options or arguments */
+ bool _is_enabled; /* True if the diagnostic command can be invoked, false otherwise */
public:
DCmdInfo(const char* name,
const char* description,
const char* impact,
+ JavaPermission permission,
int num_arguments,
bool enabled) {
this->_name = name;
this->_description = description;
this->_impact = impact;
+ this->_permission = permission;
this->_num_arguments = num_arguments;
this->_is_enabled = enabled;
}
const char* name() const { return _name; }
const char* description() const { return _description; }
const char* impact() const { return _impact; }
+ JavaPermission permission() const { return _permission; }
int num_arguments() const { return _num_arguments; }
bool is_enabled() const { return _is_enabled; }
@@ -144,16 +164,20 @@
// framework.
class DCmdArgumentInfo : public ResourceObj {
protected:
- const char* _name;
- const char* _description;
- const char* _type;
- const char* _default_string;
- bool _mandatory;
- bool _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 */
+ bool _mandatory; /* True if the option/argument is mandatory */
+ bool _option; /* True if it is an option, false if it is an argument */
+ /* (see diagnosticFramework.hpp for option/argument definitions) */
+ bool _multiple; /* True is the option can be specified several time */
+ int _position; /* Expected position for this argument (this field is */
+ /* meaningless for options) */
public:
DCmdArgumentInfo(const char* name, const char* description, const char* type,
- const char* default_string, bool mandatory, bool option) {
+ const char* default_string, bool mandatory, bool option,
+ bool multiple) {
this->_name = name;
this->_description = description;
this->_type = type;
@@ -161,11 +185,12 @@
this->_option = option;
this->_mandatory = mandatory;
this->_option = option;
+ this->_multiple = multiple;
this->_position = -1;
}
DCmdArgumentInfo(const char* name, const char* description, const char* type,
const char* default_string, bool mandatory, bool option,
- int position) {
+ bool multiple, int position) {
this->_name = name;
this->_description = description;
this->_type = type;
@@ -173,6 +198,7 @@
this->_option = option;
this->_mandatory = mandatory;
this->_option = option;
+ this->_multiple = multiple;
this->_position = position;
}
const char* name() const { return _name; }
@@ -181,11 +207,29 @@
const char* default_string() const { return _default_string; }
bool is_mandatory() const { return _mandatory; }
bool is_option() const { return _option; }
+ bool is_multiple() const { return _multiple; }
int position() const { return _position; }
};
// The DCmdParser class can be used to create an argument parser for a
// diagnostic command. It is not mandatory to use it to parse arguments.
+// The DCmdParser parses a CmdLine instance according to the parameters that
+// have been declared by its associated 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
+// position of an argument is defined relative to all arguments passed on the
+// command line, options are not considered when defining an argument position.
+// 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 option1 and option2, and three arguments. argumentA's position
+// is 0, argumentB's position is 1 and argumentC's position is 2.
class DCmdParser {
private:
GenDCmdArgument* _options;
@@ -249,6 +293,19 @@
// longer description can provide more specific details like the fact that Thread Dump
// impact depends on the heap size.
static const char* impact() { return "Low: No impact"; }
+ // The permission() method returns the description of Java Permission. This
+ // permission is required when the diagnostic command is invoked via the
+ // DiagnosticCommandMBean. The rationale for this permission check is that
+ // the DiagnosticCommandMBean can be used to perform remote invocations of
+ // diagnostic commands through the PlatformMBeanServer. The (optional) Java
+ // Permission associated with each diagnostic command should ease the work
+ // of system administrators to write policy files granting permissions to
+ // execute diagnostic commands to remote users. Any diagnostic command with
+ // a potential impact on security should overwrite this method.
+ static const JavaPermission permission() {
+ JavaPermission p = {NULL, NULL, NULL};
+ return p;
+ }
static int num_arguments() { return 0; }
outputStream* output() { return _output; }
bool is_heap_allocated() { return _is_heap_allocated; }
@@ -263,7 +320,7 @@
"The argument list of this diagnostic command should be empty.");
}
}
- virtual void execute(TRAPS) { }
+ virtual void execute(DCmdSource source, TRAPS) { }
virtual void reset(TRAPS) { }
virtual void cleanup() { }
@@ -278,7 +335,7 @@
}
// main method to invoke the framework
- static void parse_and_execute(outputStream* out, const char* cmdline,
+ static void parse_and_execute(DCmdSource source, outputStream* out, const char* cmdline,
char delim, TRAPS);
};
@@ -291,9 +348,10 @@
static const char* description() { return "No Help";}
static const char* disabled_message() { return "Diagnostic command currently disabled"; }
static const char* impact() { return "Low: No impact"; }
+ static const JavaPermission permission() {JavaPermission p = {NULL, NULL, NULL}; return p; }
static int num_arguments() { return 0; }
virtual void parse(CmdLine *line, char delim, TRAPS);
- virtual void execute(TRAPS) { }
+ virtual void execute(DCmdSource source, TRAPS) { }
virtual void reset(TRAPS);
virtual void cleanup();
virtual void print_help(const char* name);
@@ -323,6 +381,8 @@
class DCmdFactory: public CHeapObj<mtInternal> {
private:
static Mutex* _dcmdFactory_lock;
+ static bool _send_jmx_notification;
+ static bool _has_pending_jmx_notification;
// Pointer to the next factory in the singly-linked list of registered
// diagnostic commands
DCmdFactory* _next;
@@ -333,19 +393,23 @@
// When hidden, a diagnostic command doesn't appear in the list of commands
// provided by the 'help' command.
bool _hidden;
+ uint32_t _export_flags;
int _num_arguments;
static DCmdFactory* _DCmdFactoryList;
public:
- DCmdFactory(int num_arguments, bool enabled, bool hidden) {
+ DCmdFactory(int num_arguments, uint32_t flags, bool enabled, bool hidden) {
_next = NULL;
_enabled = enabled;
_hidden = hidden;
+ _export_flags = flags;
_num_arguments = num_arguments;
}
bool is_enabled() const { return _enabled; }
void set_enabled(bool b) { _enabled = b; }
bool is_hidden() const { return _hidden; }
void set_hidden(bool b) { _hidden = b; }
+ uint32_t export_flags() { return _export_flags; }
+ void set_export_flags(uint32_t f) { _export_flags = f; }
int num_arguments() { return _num_arguments; }
DCmdFactory* next() { return _next; }
virtual DCmd* create_Cheap_instance(outputStream* output) = 0;
@@ -353,19 +417,29 @@
virtual const char* name() const = 0;
virtual const char* description() const = 0;
virtual const char* impact() const = 0;
+ virtual const JavaPermission permission() const = 0;
virtual const char* disabled_message() const = 0;
// Register a DCmdFactory to make a diagnostic command available.
// Once registered, a diagnostic command must not be unregistered.
// To prevent a diagnostic command from being executed, just set the
// enabled flag to false.
static int register_DCmdFactory(DCmdFactory* factory);
- static DCmdFactory* factory(const char* cmd, size_t len);
+ static DCmdFactory* factory(DCmdSource source, const char* cmd, size_t len);
// Returns a C-heap allocated diagnostic command for the given command line
- static DCmd* create_global_DCmd(CmdLine &line, outputStream* out, TRAPS);
+ static DCmd* create_global_DCmd(DCmdSource source, CmdLine &line, outputStream* out, TRAPS);
// Returns a resourceArea allocated diagnostic command for the given command line
- static DCmd* create_local_DCmd(CmdLine &line, outputStream* out, TRAPS);
- static GrowableArray<const char*>* DCmd_list();
- static GrowableArray<DCmdInfo*>* DCmdInfo_list();
+ static DCmd* create_local_DCmd(DCmdSource source, CmdLine &line, outputStream* out, TRAPS);
+ static GrowableArray<const char*>* DCmd_list(DCmdSource source);
+ static GrowableArray<DCmdInfo*>* DCmdInfo_list(DCmdSource source);
+
+ static void set_jmx_notification_enabled(bool enabled) {
+ _send_jmx_notification = enabled;
+ }
+ static void push_jmx_notification_request();
+ static bool has_pending_jmx_notification() { return _has_pending_jmx_notification; }
+ static void send_notification(TRAPS);
+private:
+ static void send_notification_internal(TRAPS);
friend class HelpDCmd;
};
@@ -374,8 +448,8 @@
// where this template is used to create and register factories.
template <class DCmdClass> class DCmdFactoryImpl : public DCmdFactory {
public:
- DCmdFactoryImpl(bool enabled, bool hidden) :
- DCmdFactory(DCmdClass::num_arguments(), enabled, hidden) { }
+ DCmdFactoryImpl(uint32_t flags, bool enabled, bool hidden) :
+ DCmdFactory(DCmdClass::num_arguments(), flags, enabled, hidden) { }
// Returns a C-heap allocated instance
virtual DCmd* create_Cheap_instance(outputStream* output) {
return new (ResourceObj::C_HEAP, mtInternal) DCmdClass(output, true);
@@ -393,6 +467,9 @@
virtual const char* impact() const {
return DCmdClass::impact();
}
+ virtual const JavaPermission permission() const {
+ return DCmdClass::permission();
+ }
virtual const char* disabled_message() const {
return DCmdClass::disabled_message();
}
--- a/hotspot/src/share/vm/services/jmm.h Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/jmm.h Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,8 @@
JMM_VERSION_1_1 = 0x20010100, // JDK 6
JMM_VERSION_1_2 = 0x20010200, // JDK 7
JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA
- JMM_VERSION = 0x20010202
+ JMM_VERSION_1_2_2 = 0x20010202,
+ JMM_VERSION = 0x20010203
};
typedef struct {
@@ -62,7 +63,8 @@
unsigned int isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1;
unsigned int isThreadAllocatedMemorySupported : 1;
- unsigned int : 23;
+ unsigned int isRemoteDiagnosticCommandsSupported : 1;
+ unsigned int : 22;
} jmmOptionalSupport;
typedef enum {
@@ -190,21 +192,27 @@
} jmmGCStat;
typedef struct {
- const char* name;
- const char* description;
- const char* impact;
- int num_arguments;
- jboolean enabled;
+ const char* name; /* Name of the diagnostic command */
+ const char* description; /* Short description */
+ const char* impact; /* Impact on the JVM */
+ const char* permission_class; /* Class name of the required permission if any */
+ const char* permission_name; /* Permission name of the required permission if any */
+ const char* permission_action; /* Action name of the required permission if any*/
+ int num_arguments; /* Number of supported options or arguments */
+ jboolean enabled; /* True if the diagnostic command can be invoked, false otherwise */
} dcmdInfo;
typedef struct {
- const char* name;
- const char* description;
- const char* type;
- const char* default_string;
- jboolean mandatory;
- jboolean option;
- int position;
+ const char* name; /* Option/Argument name*/
+ const char* description; /* Short description */
+ const char* type; /* Type: STRING, BOOLEAN, etc. */
+ const char* default_string; /* Default value in a parsable string */
+ jboolean mandatory; /* True if the option/argument is mandatory */
+ jboolean option; /* True if it is an option, false if it is an argument */
+ /* (see diagnosticFramework.hpp for option/argument definitions) */
+ jboolean multiple; /* True if the option can be specified several time */
+ int position; /* Expected position for this argument (this field is */
+ /* meaningless for options) */
} dcmdArgInfo;
typedef struct jmmInterface_1_ {
@@ -327,6 +335,9 @@
jstring (JNICALL *ExecuteDiagnosticCommand)
(JNIEnv *env,
jstring command);
+ void (JNICALL *SetDiagnosticFrameworkNotificationEnabled)
+ (JNIEnv *env,
+ jboolean enabled);
} JmmInterface;
#ifdef __cplusplus
--- a/hotspot/src/share/vm/services/management.cpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/management.cpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,6 +68,9 @@
Klass* Management::_managementFactory_klass = NULL;
Klass* Management::_garbageCollectorImpl_klass = NULL;
Klass* Management::_gcInfo_klass = NULL;
+Klass* Management::_diagnosticCommandImpl_klass = NULL;
+Klass* Management::_managementFactoryHelper_klass = NULL;
+
jmmOptionalSupport Management::_optional_support = {0};
TimeStamp Management::_stamp;
@@ -128,11 +131,14 @@
_optional_support.isSynchronizerUsageSupported = 1;
#endif // INCLUDE_SERVICES
_optional_support.isThreadAllocatedMemorySupported = 1;
+ _optional_support.isRemoteDiagnosticCommandsSupported = 1;
// Registration of the diagnostic commands
DCmdRegistrant::register_dcmds();
DCmdRegistrant::register_dcmds_ext();
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<NMTDCmd>(true, false));
+ uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI
+ | DCmd_Source_MBean;
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<NMTDCmd>(full_export, true, false));
}
void Management::initialize(TRAPS) {
@@ -262,6 +268,20 @@
return _gcInfo_klass;
}
+Klass* Management::sun_management_DiagnosticCommandImpl_klass(TRAPS) {
+ if (_diagnosticCommandImpl_klass == NULL) {
+ _diagnosticCommandImpl_klass = load_and_initialize_klass(vmSymbols::sun_management_DiagnosticCommandImpl(), CHECK_NULL);
+ }
+ return _diagnosticCommandImpl_klass;
+}
+
+Klass* Management::sun_management_ManagementFactoryHelper_klass(TRAPS) {
+ if (_managementFactoryHelper_klass == NULL) {
+ _managementFactoryHelper_klass = load_and_initialize_klass(vmSymbols::sun_management_ManagementFactoryHelper(), CHECK_NULL);
+ }
+ return _managementFactoryHelper_klass;
+}
+
static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) {
Handle snapshot_thread(THREAD, snapshot->threadObj());
@@ -2144,7 +2164,7 @@
JVM_ENTRY(jobjectArray, jmm_GetDiagnosticCommands(JNIEnv *env))
ResourceMark rm(THREAD);
- GrowableArray<const char *>* dcmd_list = DCmdFactory::DCmd_list();
+ GrowableArray<const char *>* dcmd_list = DCmdFactory::DCmd_list(DCmd_Source_MBean);
objArrayOop cmd_array_oop = oopFactory::new_objArray(SystemDictionary::String_klass(),
dcmd_list->length(), CHECK_NULL);
objArrayHandle cmd_array(THREAD, cmd_array_oop);
@@ -2173,7 +2193,7 @@
"Array element type is not String class");
}
- GrowableArray<DCmdInfo *>* info_list = DCmdFactory::DCmdInfo_list();
+ GrowableArray<DCmdInfo *>* info_list = DCmdFactory::DCmdInfo_list(DCmd_Source_MBean);
int num_cmds = cmds_ah->length();
for (int i = 0; i < num_cmds; i++) {
@@ -2196,6 +2216,10 @@
infoArray[i].name = info->name();
infoArray[i].description = info->description();
infoArray[i].impact = info->impact();
+ JavaPermission p = info->permission();
+ infoArray[i].permission_class = p._class;
+ infoArray[i].permission_name = p._name;
+ infoArray[i].permission_action = p._action;
infoArray[i].num_arguments = info->num_arguments();
infoArray[i].enabled = info->is_enabled();
}
@@ -2215,7 +2239,8 @@
"Command line content cannot be null.");
}
DCmd* dcmd = NULL;
- DCmdFactory*factory = DCmdFactory::factory(cmd_name, strlen(cmd_name));
+ DCmdFactory*factory = DCmdFactory::factory(DCmd_Source_MBean, cmd_name,
+ strlen(cmd_name));
if (factory != NULL) {
dcmd = factory->create_resource_instance(NULL);
}
@@ -2235,6 +2260,7 @@
infoArray[i].default_string = array->at(i)->default_string();
infoArray[i].mandatory = array->at(i)->is_mandatory();
infoArray[i].option = array->at(i)->is_option();
+ infoArray[i].multiple = array->at(i)->is_multiple();
infoArray[i].position = array->at(i)->position();
}
return;
@@ -2253,11 +2279,15 @@
"Command line content cannot be null.");
}
bufferedStream output;
- DCmd::parse_and_execute(&output, cmdline, ' ', CHECK_NULL);
+ DCmd::parse_and_execute(DCmd_Source_MBean, &output, cmdline, ' ', CHECK_NULL);
oop result = java_lang_String::create_oop_from_str(output.as_string(), CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result);
JVM_END
+JVM_ENTRY(void, jmm_SetDiagnosticFrameworkNotificationEnabled(JNIEnv *env, jboolean enabled))
+ DCmdFactory::set_jmx_notification_enabled(enabled?true:false);
+JVM_END
+
jlong Management::ticks_to_ms(jlong ticks) {
assert(os::elapsed_frequency() > 0, "Must be non-zero");
return (jlong)(((double)ticks / (double)os::elapsed_frequency())
@@ -2304,7 +2334,8 @@
jmm_GetDiagnosticCommands,
jmm_GetDiagnosticCommandInfo,
jmm_GetDiagnosticCommandArgumentsInfo,
- jmm_ExecuteDiagnosticCommand
+ jmm_ExecuteDiagnosticCommand,
+ jmm_SetDiagnosticFrameworkNotificationEnabled
};
#endif // INCLUDE_MANAGEMENT
--- a/hotspot/src/share/vm/services/management.hpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/management.hpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,8 @@
static Klass* _garbageCollectorMXBean_klass;
static Klass* _managementFactory_klass;
static Klass* _garbageCollectorImpl_klass;
+ static Klass* _diagnosticCommandImpl_klass;
+ static Klass* _managementFactoryHelper_klass;
static Klass* _gcInfo_klass;
static Klass* load_and_initialize_klass(Symbol* sh, TRAPS);
@@ -99,6 +101,10 @@
NOT_MANAGEMENT_RETURN_(NULL);
static Klass* com_sun_management_GcInfo_klass(TRAPS)
NOT_MANAGEMENT_RETURN_(NULL);
+ static Klass* sun_management_DiagnosticCommandImpl_klass(TRAPS)
+ NOT_MANAGEMENT_RETURN_(NULL);
+ static Klass* sun_management_ManagementFactoryHelper_klass(TRAPS)
+ NOT_MANAGEMENT_RETURN_(NULL);
static instanceOop create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS);
static instanceOop create_thread_info_instance(ThreadSnapshot* snapshot, objArrayHandle monitors_array, typeArrayHandle depths_array, objArrayHandle synchronizers_array, TRAPS);
--- a/hotspot/src/share/vm/services/nmtDCmd.cpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/nmtDCmd.cpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -71,7 +71,7 @@
_dcmdparser.add_dcmd_option(&_scale);
}
-void NMTDCmd::execute(TRAPS) {
+void NMTDCmd::execute(DCmdSource source, TRAPS) {
const char* scale_value = _scale.value();
size_t scale_unit;
if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) {
--- a/hotspot/src/share/vm/services/nmtDCmd.hpp Fri May 03 12:26:15 2013 +0200
+++ b/hotspot/src/share/vm/services/nmtDCmd.hpp Fri May 03 05:17:15 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -52,10 +52,15 @@
return "Print native memory usage";
}
static const char* impact() {
- return "Medium:";
+ return "Medium";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
}
static int num_arguments();
- virtual void execute(TRAPS);
+ virtual void execute(DCmdSource source, TRAPS);
};
#endif // SHARE_VM_SERVICES_NMT_DCMD_HPP