Merge
This commit is contained in:
commit
7e7edc4cfa
@ -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") \
|
||||
|
@ -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 @@ 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
|
||||
|
@ -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 @@ 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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
DCmdFactory* DCmdFactory::factory(const char* name, size_t len) {
|
||||
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(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();
|
||||
}
|
||||
|
@ -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 @@ 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();
|
||||
}
|
||||
|
@ -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 @@ 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
|
||||
|
@ -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::_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
|
||||
|
||||
|
@ -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 @@ 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);
|
||||
|
@ -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 @@ 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) {
|
||||
|
@ -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 @@ 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
|
||||
|
Loading…
Reference in New Issue
Block a user