提交 107bdbd8 编写于 作者: F fparain

Merge

......@@ -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") \
......
/*
* 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 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
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 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
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 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
if(has_gc_notification_event) {
GCNotifier::sendNotification(CHECK);
}
if(has_dcmd_notification_event) {
DCmdFactory::send_notification(CHECK);
}
}
}
......
......@@ -157,7 +157,7 @@ static jint jcmd(AttachOperation* op, outputStream* out) {
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();
......
......@@ -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 @@ HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, hea
_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 @@ void HelpDCmd::execute(TRAPS) {
}
} 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 @@ int HelpDCmd::num_arguments() {
}
}
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 @@ PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :
_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 @@ int PrintVMFlagsDCmd::num_arguments() {
}
}
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 @@ VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
_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 @@ int VMUptimeDCmd::num_arguments() {
}
}
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 @@ HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
_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 @@ ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
_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 @@ ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) :
_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 @@ ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
_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 @@ int JMXStartRemoteDCmd::num_arguments() {
}
}
void JMXStartRemoteDCmd::execute(TRAPS) {
void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
......@@ -593,7 +611,7 @@ JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated)
// do nothing
}
void JMXStartLocalDCmd::execute(TRAPS) {
void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
......@@ -611,7 +629,7 @@ void JMXStartLocalDCmd::execute(TRAPS) {
}
void JMXStopRemoteDCmd::execute(TRAPS) {
void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
......
......@@ -51,7 +51,7 @@ public:
}
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
return "Low";
}
static int num_arguments();
virtual void execute(TRAPS);
virtual void execute(DCmdSource source, TRAPS);
};
class SystemGCDCmd : public DCmd {
......@@ -139,7 +159,7 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
static int num_arguments();
virtual void execute(TRAPS);
virtual void execute(DCmdSource source, TRAPS);
};
......@@ -302,7 +337,7 @@ public:
return "Start local management agent.";
}
virtual void execute(TRAPS);
virtual void execute(DCmdSource source, TRAPS);
};
......@@ -321,7 +356,7 @@ public:
return "Stop remote management agent.";
}
virtual void execute(TRAPS);
virtual void execute(DCmdSource source, TRAPS);
};
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
/*
* 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 @@ GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() {
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 @@ GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() {
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 @@ GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() {
return _dcmdparser.argument_info_array();
}
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);
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(const char* name, size_t len) {
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 @@ int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
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 @@ DCmd* DCmdFactory::create_global_DCmd(CmdLine &line, outputStream* out, TRAPS) {
"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 @@ DCmd* DCmdFactory::create_local_DCmd(CmdLine &line, outputStream* out, TRAPS) {
"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 @@ GrowableArray<const char*>* DCmdFactory::DCmd_list() {
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();
}
......
/*
* 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 @@ public:
// 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 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
"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 @@ public:
}
// 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 @@ public:
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 @@ public:
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 @@ private:
// 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 @@ public:
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 @@ public:
// 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 @@ public:
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();
}
......
/*
* 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 @@ enum {
JMM_VERSION_1_1 = 0x20010100, // JDK 6
JMM_VERSION_1_2 = 0x20010200, // JDK 7
JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA
JMM_VERSION = 0x20010202
JMM_VERSION_1_2_2 = 0x20010202,
JMM_VERSION = 0x20010203
};
typedef struct {
......@@ -62,7 +63,8 @@ typedef struct {
unsigned int isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1;
unsigned int isThreadAllocatedMemorySupported : 1;
unsigned int : 23;
unsigned int isRemoteDiagnosticCommandsSupported : 1;
unsigned int : 22;
} jmmOptionalSupport;
typedef enum {
......@@ -190,21 +192,27 @@ typedef struct {
} jmmGCStat;
typedef struct {
const char* name;
const char* description;
const char* impact;
int num_arguments;
jboolean enabled;
const char* name; /* Name of the diagnostic command */
const char* description; /* Short description */
const char* impact; /* Impact on the JVM */
const char* permission_class; /* Class name of the required permission if any */
const char* permission_name; /* Permission name of the required permission if any */
const char* permission_action; /* Action name of the required permission if any*/
int num_arguments; /* Number of supported options or arguments */
jboolean enabled; /* True if the diagnostic command can be invoked, false otherwise */
} dcmdInfo;
typedef struct {
const char* name;
const char* description;
const char* type;
const char* default_string;
jboolean mandatory;
jboolean option;
int position;
const char* name; /* Option/Argument name*/
const char* description; /* Short description */
const char* type; /* Type: STRING, BOOLEAN, etc. */
const char* default_string; /* Default value in a parsable string */
jboolean mandatory; /* True if the option/argument is mandatory */
jboolean option; /* True if it is an option, false if it is an argument */
/* (see diagnosticFramework.hpp for option/argument definitions) */
jboolean multiple; /* True 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 @@ typedef struct jmmInterface_1_ {
jstring (JNICALL *ExecuteDiagnosticCommand)
(JNIEnv *env,
jstring command);
void (JNICALL *SetDiagnosticFrameworkNotificationEnabled)
(JNIEnv *env,
jboolean enabled);
} JmmInterface;
#ifdef __cplusplus
......
/*
* 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::_garbageCollectorMXBean_klass = NULL;
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 @@ void Management::init() {
_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 @@ Klass* Management::com_sun_management_GcInfo_klass(TRAPS) {
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_END
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 @@ JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
"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 @@ JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
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 @@ JVM_ENTRY(void, jmm_GetDiagnosticCommandArgumentsInfo(JNIEnv *env,
"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 @@ JVM_ENTRY(void, jmm_GetDiagnosticCommandArgumentsInfo(JNIEnv *env,
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 @@ JVM_ENTRY(jstring, jmm_ExecuteDiagnosticCommand(JNIEnv *env, jstring commandline
"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 @@ const struct jmmInterface_1_ jmm_interface = {
jmm_GetDiagnosticCommands,
jmm_GetDiagnosticCommandInfo,
jmm_GetDiagnosticCommandArgumentsInfo,
jmm_ExecuteDiagnosticCommand
jmm_ExecuteDiagnosticCommand,
jmm_SetDiagnosticFrameworkNotificationEnabled
};
#endif // INCLUDE_MANAGEMENT
......
/*
* 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 @@ private:
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 @@ public:
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);
......
/*
* 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 @@ NMTDCmd::NMTDCmd(outputStream* output,
_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) {
......
/*
* 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 @@ class NMTDCmd: public DCmdWithParser {
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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册