7120511: Add diagnostic commands
Reviewed-by: acorn, phh, dcubed, sspitsyn
This commit is contained in:
parent
66388c03c9
commit
849571d5b3
@ -296,6 +296,7 @@
|
|||||||
template(finalize_method_name, "finalize") \
|
template(finalize_method_name, "finalize") \
|
||||||
template(reference_lock_name, "lock") \
|
template(reference_lock_name, "lock") \
|
||||||
template(reference_discovered_name, "discovered") \
|
template(reference_discovered_name, "discovered") \
|
||||||
|
template(run_finalization_name, "runFinalization") \
|
||||||
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
|
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
|
||||||
template(uncaughtException_name, "uncaughtException") \
|
template(uncaughtException_name, "uncaughtException") \
|
||||||
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
|
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
|
||||||
|
@ -2323,7 +2323,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
|||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
// -Xprintflags
|
// -Xprintflags
|
||||||
} else if (match_option(option, "-Xprintflags", &tail)) {
|
} else if (match_option(option, "-Xprintflags", &tail)) {
|
||||||
CommandLineFlags::printFlags();
|
CommandLineFlags::printFlags(tty, false);
|
||||||
vm_exit(0);
|
vm_exit(0);
|
||||||
#endif
|
#endif
|
||||||
// -D
|
// -D
|
||||||
@ -2971,13 +2971,13 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
|||||||
IgnoreUnrecognizedVMOptions = false;
|
IgnoreUnrecognizedVMOptions = false;
|
||||||
}
|
}
|
||||||
if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) {
|
if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) {
|
||||||
CommandLineFlags::printFlags();
|
CommandLineFlags::printFlags(tty, false);
|
||||||
vm_exit(0);
|
vm_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) {
|
if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) {
|
||||||
CommandLineFlags::printFlags(true);
|
CommandLineFlags::printFlags(tty, true);
|
||||||
vm_exit(0);
|
vm_exit(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3170,7 +3170,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (PrintCommandLineFlags) {
|
if (PrintCommandLineFlags) {
|
||||||
CommandLineFlags::printSetFlags();
|
CommandLineFlags::printSetFlags(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply CPU specific policy for the BiasedLocking
|
// Apply CPU specific policy for the BiasedLocking
|
||||||
|
@ -488,7 +488,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineFlags::printSetFlags() {
|
void CommandLineFlags::printSetFlags(outputStream* out) {
|
||||||
// Print which flags were set on the command line
|
// Print which flags were set on the command line
|
||||||
// note: this method is called before the thread structure is in place
|
// note: this method is called before the thread structure is in place
|
||||||
// which means resource allocation cannot be used.
|
// which means resource allocation cannot be used.
|
||||||
@ -507,11 +507,11 @@ void CommandLineFlags::printSetFlags() {
|
|||||||
// Print
|
// Print
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
if (array[i]->origin /* naked field! */) {
|
if (array[i]->origin /* naked field! */) {
|
||||||
array[i]->print_as_flag(tty);
|
array[i]->print_as_flag(out);
|
||||||
tty->print(" ");
|
out->print(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tty->cr();
|
out->cr();
|
||||||
FREE_C_HEAP_ARRAY(Flag*, array);
|
FREE_C_HEAP_ARRAY(Flag*, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ void CommandLineFlags::verify() {
|
|||||||
|
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
void CommandLineFlags::printFlags(bool withComments) {
|
void CommandLineFlags::printFlags(outputStream* out, bool withComments) {
|
||||||
// Print the flags sorted by name
|
// Print the flags sorted by name
|
||||||
// note: this method is called before the thread structure is in place
|
// note: this method is called before the thread structure is in place
|
||||||
// which means resource allocation cannot be used.
|
// which means resource allocation cannot be used.
|
||||||
@ -541,10 +541,10 @@ void CommandLineFlags::printFlags(bool withComments) {
|
|||||||
qsort(array, length, sizeof(Flag*), compare_flags);
|
qsort(array, length, sizeof(Flag*), compare_flags);
|
||||||
|
|
||||||
// Print
|
// Print
|
||||||
tty->print_cr("[Global flags]");
|
out->print_cr("[Global flags]");
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
if (array[i]->is_unlocked()) {
|
if (array[i]->is_unlocked()) {
|
||||||
array[i]->print_on(tty, withComments);
|
array[i]->print_on(out, withComments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE_C_HEAP_ARRAY(Flag*, array);
|
FREE_C_HEAP_ARRAY(Flag*, array);
|
||||||
|
@ -326,9 +326,9 @@ class CommandLineFlags {
|
|||||||
|
|
||||||
// Returns false if name is not a command line flag.
|
// Returns false if name is not a command line flag.
|
||||||
static bool wasSetOnCmdline(const char* name, bool* value);
|
static bool wasSetOnCmdline(const char* name, bool* value);
|
||||||
static void printSetFlags();
|
static void printSetFlags(outputStream* out);
|
||||||
|
|
||||||
static void printFlags(bool withComments = false );
|
static void printFlags(outputStream* out, bool withComments);
|
||||||
|
|
||||||
static void verify() PRODUCT_RETURN;
|
static void verify() PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
@ -140,7 +140,7 @@ jint init_globals() {
|
|||||||
// All the flags that get adjusted by VM_Version_init and os::init_2
|
// All the flags that get adjusted by VM_Version_init and os::init_2
|
||||||
// have been set so dump the flags now.
|
// have been set so dump the flags now.
|
||||||
if (PrintFlagsFinal) {
|
if (PrintFlagsFinal) {
|
||||||
CommandLineFlags::printFlags();
|
CommandLineFlags::printFlags(tty, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
|
@ -99,6 +99,7 @@ static jint get_properties(AttachOperation* op, outputStream* out, Symbol* seria
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of "properties" command.
|
// Implementation of "properties" command.
|
||||||
|
// See also: PrintSystemPropertiesDCmd class
|
||||||
static jint get_system_properties(AttachOperation* op, outputStream* out) {
|
static jint get_system_properties(AttachOperation* op, outputStream* out) {
|
||||||
return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name());
|
return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name());
|
||||||
}
|
}
|
||||||
@ -127,6 +128,7 @@ static jint data_dump(AttachOperation* op, outputStream* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of "threaddump" command - essentially a remote ctrl-break
|
// Implementation of "threaddump" command - essentially a remote ctrl-break
|
||||||
|
// See also: ThreadDumpDCmd class
|
||||||
//
|
//
|
||||||
static jint thread_dump(AttachOperation* op, outputStream* out) {
|
static jint thread_dump(AttachOperation* op, outputStream* out) {
|
||||||
bool print_concurrent_locks = false;
|
bool print_concurrent_locks = false;
|
||||||
@ -158,6 +160,7 @@ static jint jcmd(AttachOperation* op, outputStream* out) {
|
|||||||
DCmd::parse_and_execute(out, op->arg(0), ' ', THREAD);
|
DCmd::parse_and_execute(out, op->arg(0), ' ', THREAD);
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
java_lang_Throwable::print(PENDING_EXCEPTION, out);
|
java_lang_Throwable::print(PENDING_EXCEPTION, out);
|
||||||
|
out->cr();
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
// The exception has been printed on the output stream
|
// The exception has been printed on the output stream
|
||||||
// If the JVM returns JNI_ERR, the attachAPI throws a generic I/O
|
// If the JVM returns JNI_ERR, the attachAPI throws a generic I/O
|
||||||
@ -169,6 +172,7 @@ static jint jcmd(AttachOperation* op, outputStream* out) {
|
|||||||
|
|
||||||
#ifndef SERVICES_KERNEL // Heap dumping not supported
|
#ifndef SERVICES_KERNEL // Heap dumping not supported
|
||||||
// Implementation of "dumpheap" command.
|
// Implementation of "dumpheap" command.
|
||||||
|
// See also: HeapDumpDCmd class
|
||||||
//
|
//
|
||||||
// Input arguments :-
|
// Input arguments :-
|
||||||
// arg0: Name of the dump file
|
// arg0: Name of the dump file
|
||||||
@ -211,6 +215,7 @@ jint dump_heap(AttachOperation* op, outputStream* out) {
|
|||||||
#endif // SERVICES_KERNEL
|
#endif // SERVICES_KERNEL
|
||||||
|
|
||||||
// Implementation of "inspectheap" command
|
// Implementation of "inspectheap" command
|
||||||
|
// See also: ClassHistogramDCmd class
|
||||||
//
|
//
|
||||||
// Input arguments :-
|
// Input arguments :-
|
||||||
// arg0: "-live" or "-all"
|
// arg0: "-live" or "-all"
|
||||||
@ -354,6 +359,7 @@ static jint set_flag(AttachOperation* op, outputStream* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of "printflag" command
|
// Implementation of "printflag" command
|
||||||
|
// See also: PrintVMFlagsDCmd class
|
||||||
static jint print_flag(AttachOperation* op, outputStream* out) {
|
static jint print_flag(AttachOperation* op, outputStream* out) {
|
||||||
const char* name = NULL;
|
const char* name = NULL;
|
||||||
if ((name = op->arg(0)) == NULL) {
|
if ((name = op->arg(0)) == NULL) {
|
||||||
|
@ -23,11 +23,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "gc_implementation/shared/vmGCOperations.hpp"
|
||||||
|
#include "runtime/javaCalls.hpp"
|
||||||
#include "services/diagnosticArgument.hpp"
|
#include "services/diagnosticArgument.hpp"
|
||||||
#include "services/diagnosticCommand.hpp"
|
#include "services/diagnosticCommand.hpp"
|
||||||
#include "services/diagnosticFramework.hpp"
|
#include "services/diagnosticFramework.hpp"
|
||||||
|
#include "services/heapDumper.hpp"
|
||||||
|
#include "services/management.hpp"
|
||||||
|
|
||||||
HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmd(output, heap),
|
HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
|
||||||
_all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
|
_all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
|
||||||
_cmd("command name", "The name of the command for which we want help",
|
_cmd("command name", "The name of the command for which we want help",
|
||||||
"STRING", false) {
|
"STRING", false) {
|
||||||
@ -35,14 +39,6 @@ HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmd(output, heap),
|
|||||||
_dcmdparser.add_dcmd_argument(&_cmd);
|
_dcmdparser.add_dcmd_argument(&_cmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
void HelpDCmd::parse(CmdLine* line, char delim, TRAPS) {
|
|
||||||
_dcmdparser.parse(line, delim, CHECK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HelpDCmd::print_help(outputStream* out) {
|
|
||||||
_dcmdparser.print_help(out, name());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HelpDCmd::execute(TRAPS) {
|
void HelpDCmd::execute(TRAPS) {
|
||||||
if (_all.value()) {
|
if (_all.value()) {
|
||||||
GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list();
|
GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list();
|
||||||
@ -66,10 +62,11 @@ void HelpDCmd::execute(TRAPS) {
|
|||||||
factory->is_enabled() ? "" : " [disabled]");
|
factory->is_enabled() ? "" : " [disabled]");
|
||||||
output()->print_cr(factory->description());
|
output()->print_cr(factory->description());
|
||||||
output()->print_cr("\nImpact: %s", factory->impact());
|
output()->print_cr("\nImpact: %s", factory->impact());
|
||||||
|
output()->cr();
|
||||||
cmd = factory->create_resource_instance(output());
|
cmd = factory->create_resource_instance(output());
|
||||||
if (cmd != NULL) {
|
if (cmd != NULL) {
|
||||||
DCmdMark mark(cmd);
|
DCmdMark mark(cmd);
|
||||||
cmd->print_help(output());
|
cmd->print_help(factory->name());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());
|
output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());
|
||||||
@ -90,14 +87,6 @@ void HelpDCmd::execute(TRAPS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelpDCmd::reset(TRAPS) {
|
|
||||||
_dcmdparser.reset(CHECK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HelpDCmd::cleanup() {
|
|
||||||
_dcmdparser.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
int HelpDCmd::num_arguments() {
|
int HelpDCmd::num_arguments() {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
HelpDCmd* dcmd = new HelpDCmd(NULL, false);
|
HelpDCmd* dcmd = new HelpDCmd(NULL, false);
|
||||||
@ -109,14 +98,6 @@ int HelpDCmd::num_arguments() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrowableArray<const char*>* HelpDCmd::argument_name_array() {
|
|
||||||
return _dcmdparser.argument_name_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
GrowableArray<DCmdArgumentInfo*>* HelpDCmd::argument_info_array() {
|
|
||||||
return _dcmdparser.argument_info_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionDCmd::execute(TRAPS) {
|
void VersionDCmd::execute(TRAPS) {
|
||||||
output()->print_cr("%s version %s", Abstract_VM_Version::vm_name(),
|
output()->print_cr("%s version %s", Abstract_VM_Version::vm_name(),
|
||||||
Abstract_VM_Version::vm_release());
|
Abstract_VM_Version::vm_release());
|
||||||
@ -129,3 +110,210 @@ void VersionDCmd::execute(TRAPS) {
|
|||||||
jdk_version.minor_version());
|
jdk_version.minor_version());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :
|
||||||
|
DCmdWithParser(output, heap),
|
||||||
|
_all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") {
|
||||||
|
_dcmdparser.add_dcmd_option(&_all);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintVMFlagsDCmd::execute(TRAPS) {
|
||||||
|
if (_all.value()) {
|
||||||
|
CommandLineFlags::printFlags(output(), true);
|
||||||
|
} else {
|
||||||
|
CommandLineFlags::printSetFlags(output());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PrintVMFlagsDCmd::num_arguments() {
|
||||||
|
ResourceMark rm;
|
||||||
|
PrintVMFlagsDCmd* dcmd = new PrintVMFlagsDCmd(NULL, false);
|
||||||
|
if (dcmd != NULL) {
|
||||||
|
DCmdMark mark(dcmd);
|
||||||
|
return dcmd->_dcmdparser.num_arguments();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintSystemPropertiesDCmd::execute(TRAPS) {
|
||||||
|
// load sun.misc.VMSupport
|
||||||
|
Symbol* klass = vmSymbols::sun_misc_VMSupport();
|
||||||
|
klassOop k = SystemDictionary::resolve_or_fail(klass, true, CHECK);
|
||||||
|
instanceKlassHandle ik (THREAD, k);
|
||||||
|
if (ik->should_be_initialized()) {
|
||||||
|
ik->initialize(THREAD);
|
||||||
|
}
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
java_lang_Throwable::print(PENDING_EXCEPTION, output());
|
||||||
|
output()->cr();
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoke the serializePropertiesToByteArray method
|
||||||
|
JavaValue result(T_OBJECT);
|
||||||
|
JavaCallArguments args;
|
||||||
|
|
||||||
|
Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();
|
||||||
|
JavaCalls::call_static(&result,
|
||||||
|
ik,
|
||||||
|
vmSymbols::serializePropertiesToByteArray_name(),
|
||||||
|
signature,
|
||||||
|
&args,
|
||||||
|
THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
java_lang_Throwable::print(PENDING_EXCEPTION, output());
|
||||||
|
output()->cr();
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The result should be a [B
|
||||||
|
oop res = (oop)result.get_jobject();
|
||||||
|
assert(res->is_typeArray(), "just checking");
|
||||||
|
assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
|
||||||
|
|
||||||
|
// copy the bytes to the output stream
|
||||||
|
typeArrayOop ba = typeArrayOop(res);
|
||||||
|
jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
|
||||||
|
output()->print_raw((const char*)addr, ba->length());
|
||||||
|
}
|
||||||
|
|
||||||
|
VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
|
||||||
|
DCmdWithParser(output, heap),
|
||||||
|
_date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
|
||||||
|
_dcmdparser.add_dcmd_option(&_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMUptimeDCmd::execute(TRAPS) {
|
||||||
|
if (_date.value()) {
|
||||||
|
output()->date_stamp(true, "", ": ");
|
||||||
|
}
|
||||||
|
output()->time_stamp().update_to(tty->time_stamp().ticks());
|
||||||
|
output()->stamp();
|
||||||
|
output()->print_cr(" s");
|
||||||
|
}
|
||||||
|
|
||||||
|
int VMUptimeDCmd::num_arguments() {
|
||||||
|
ResourceMark rm;
|
||||||
|
VMUptimeDCmd* dcmd = new VMUptimeDCmd(NULL, false);
|
||||||
|
if (dcmd != NULL) {
|
||||||
|
DCmdMark mark(dcmd);
|
||||||
|
return dcmd->_dcmdparser.num_arguments();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemGCDCmd::execute(TRAPS) {
|
||||||
|
Universe::heap()->collect(GCCause::_java_lang_system_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunFinalizationDCmd::execute(TRAPS) {
|
||||||
|
klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(),
|
||||||
|
true, CHECK);
|
||||||
|
instanceKlassHandle klass(THREAD, k);
|
||||||
|
JavaValue result(T_VOID);
|
||||||
|
JavaCalls::call_static(&result, klass,
|
||||||
|
vmSymbols::run_finalization_name(),
|
||||||
|
vmSymbols::void_method_signature(), CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SERVICES_KERNEL // Heap dumping not supported
|
||||||
|
HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
|
||||||
|
DCmdWithParser(output, heap),
|
||||||
|
_filename("filename","Name of the dump file", "STRING",true),
|
||||||
|
_all("-all", "Dump all objects, including unreachable objects",
|
||||||
|
"BOOLEAN", false, "false") {
|
||||||
|
_dcmdparser.add_dcmd_option(&_all);
|
||||||
|
_dcmdparser.add_dcmd_argument(&_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeapDumpDCmd::execute(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.
|
||||||
|
HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
|
||||||
|
int res = dumper.dump(_filename.value());
|
||||||
|
if (res == 0) {
|
||||||
|
output()->print_cr("Heap dump file created");
|
||||||
|
} else {
|
||||||
|
// heap dump failed
|
||||||
|
ResourceMark rm;
|
||||||
|
char* error = dumper.error_as_C_string();
|
||||||
|
if (error == NULL) {
|
||||||
|
output()->print_cr("Dump failed - reason unknown");
|
||||||
|
} else {
|
||||||
|
output()->print_cr("%s", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HeapDumpDCmd::num_arguments() {
|
||||||
|
ResourceMark rm;
|
||||||
|
HeapDumpDCmd* dcmd = new HeapDumpDCmd(NULL, false);
|
||||||
|
if (dcmd != NULL) {
|
||||||
|
DCmdMark mark(dcmd);
|
||||||
|
return dcmd->_dcmdparser.num_arguments();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SERVICES_KERNEL
|
||||||
|
|
||||||
|
ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
|
||||||
|
DCmdWithParser(output, heap),
|
||||||
|
_all("-all", "Inspect all objects, including unreachable objects",
|
||||||
|
"BOOLEAN", false, "false") {
|
||||||
|
_dcmdparser.add_dcmd_option(&_all);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassHistogramDCmd::execute(TRAPS) {
|
||||||
|
VM_GC_HeapInspection heapop(output(),
|
||||||
|
!_all.value() /* request full gc if false */,
|
||||||
|
true /* need_prologue */);
|
||||||
|
VMThread::execute(&heapop);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClassHistogramDCmd::num_arguments() {
|
||||||
|
ResourceMark rm;
|
||||||
|
ClassHistogramDCmd* dcmd = new ClassHistogramDCmd(NULL, false);
|
||||||
|
if (dcmd != NULL) {
|
||||||
|
DCmdMark mark(dcmd);
|
||||||
|
return dcmd->_dcmdparser.num_arguments();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
|
||||||
|
DCmdWithParser(output, heap),
|
||||||
|
_locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") {
|
||||||
|
_dcmdparser.add_dcmd_option(&_locks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadDumpDCmd::execute(TRAPS) {
|
||||||
|
// thread stacks
|
||||||
|
VM_PrintThreads op1(output(), _locks.value());
|
||||||
|
VMThread::execute(&op1);
|
||||||
|
|
||||||
|
// JNI global handles
|
||||||
|
VM_PrintJNI op2(output());
|
||||||
|
VMThread::execute(&op2);
|
||||||
|
|
||||||
|
// Deadlock detection
|
||||||
|
VM_FindDeadlocks op3(output());
|
||||||
|
VMThread::execute(&op3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThreadDumpDCmd::num_arguments() {
|
||||||
|
ResourceMark rm;
|
||||||
|
ThreadDumpDCmd* dcmd = new ThreadDumpDCmd(NULL, false);
|
||||||
|
if (dcmd != NULL) {
|
||||||
|
DCmdMark mark(dcmd);
|
||||||
|
return dcmd->_dcmdparser.num_arguments();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -35,9 +35,8 @@
|
|||||||
#include "services/diagnosticCommand.hpp"
|
#include "services/diagnosticCommand.hpp"
|
||||||
#include "services/diagnosticFramework.hpp"
|
#include "services/diagnosticFramework.hpp"
|
||||||
|
|
||||||
class HelpDCmd : public DCmd {
|
class HelpDCmd : public DCmdWithParser {
|
||||||
protected:
|
protected:
|
||||||
DCmdParser _dcmdparser;
|
|
||||||
DCmdArgument<bool> _all;
|
DCmdArgument<bool> _all;
|
||||||
DCmdArgument<char*> _cmd;
|
DCmdArgument<char*> _cmd;
|
||||||
public:
|
public:
|
||||||
@ -50,13 +49,7 @@ public:
|
|||||||
}
|
}
|
||||||
static const char* impact() { return "Low: "; }
|
static const char* impact() { return "Low: "; }
|
||||||
static int num_arguments();
|
static int num_arguments();
|
||||||
virtual void parse(CmdLine* line, char delim, TRAPS);
|
|
||||||
virtual void execute(TRAPS);
|
virtual void execute(TRAPS);
|
||||||
virtual void reset(TRAPS);
|
|
||||||
virtual void cleanup();
|
|
||||||
virtual void print_help(outputStream* out);
|
|
||||||
virtual GrowableArray<const char*>* argument_name_array();
|
|
||||||
virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class VersionDCmd : public DCmd {
|
class VersionDCmd : public DCmd {
|
||||||
@ -68,9 +61,156 @@ public:
|
|||||||
}
|
}
|
||||||
static const char* impact() { return "Low: "; }
|
static const char* impact() { return "Low: "; }
|
||||||
static int num_arguments() { return 0; }
|
static int num_arguments() { return 0; }
|
||||||
virtual void parse(CmdLine* line, char delim, TRAPS) { }
|
|
||||||
virtual void execute(TRAPS);
|
virtual void execute(TRAPS);
|
||||||
virtual void print_help(outputStream* out) { }
|
};
|
||||||
|
|
||||||
|
class CommandLineDCmd : public DCmd {
|
||||||
|
public:
|
||||||
|
CommandLineDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
|
||||||
|
static const char* name() { return "VM.command_line"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Print the command line used to start this VM instance.";
|
||||||
|
}
|
||||||
|
static const char* impact() { return "Low: "; }
|
||||||
|
static int num_arguments() { return 0; }
|
||||||
|
virtual void execute(TRAPS) {
|
||||||
|
Arguments::print_on(_output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// See also: get_system_properties in attachListener.cpp
|
||||||
|
class PrintSystemPropertiesDCmd : public DCmd {
|
||||||
|
public:
|
||||||
|
PrintSystemPropertiesDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
|
||||||
|
static const char* name() { return "VM.system_properties"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Print system properties.";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "Low: ";
|
||||||
|
}
|
||||||
|
static int num_arguments() { return 0; }
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
// See also: print_flag in attachListener.cpp
|
||||||
|
class PrintVMFlagsDCmd : public DCmdWithParser {
|
||||||
|
protected:
|
||||||
|
DCmdArgument<bool> _all;
|
||||||
|
public:
|
||||||
|
PrintVMFlagsDCmd(outputStream* output, bool heap);
|
||||||
|
static const char* name() { return "VM.flags"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Print VM flag options and their current values.";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "Low: ";
|
||||||
|
}
|
||||||
|
static int num_arguments();
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
class VMUptimeDCmd : public DCmdWithParser {
|
||||||
|
protected:
|
||||||
|
DCmdArgument<bool> _date;
|
||||||
|
public:
|
||||||
|
VMUptimeDCmd(outputStream* output, bool heap);
|
||||||
|
static const char* name() { return "VM.uptime"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Print VM uptime.";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "Low: ";
|
||||||
|
}
|
||||||
|
static int num_arguments();
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SystemGCDCmd : public DCmd {
|
||||||
|
public:
|
||||||
|
SystemGCDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
|
||||||
|
static const char* name() { return "GC.run"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Call java.lang.System.gc().";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "Medium: Depends on Java heap size and content.";
|
||||||
|
}
|
||||||
|
static int num_arguments() { return 0; }
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RunFinalizationDCmd : public DCmd {
|
||||||
|
public:
|
||||||
|
RunFinalizationDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
|
||||||
|
static const char* name() { return "GC.run_finalization"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Call java.lang.System.runFinalization().";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "Medium: Depends on Java content.";
|
||||||
|
}
|
||||||
|
static int num_arguments() { return 0; }
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef SERVICES_KERNEL // Heap dumping not supported
|
||||||
|
// See also: dump_heap in attachListener.cpp
|
||||||
|
class HeapDumpDCmd : public DCmdWithParser {
|
||||||
|
protected:
|
||||||
|
DCmdArgument<char*> _filename;
|
||||||
|
DCmdArgument<bool> _all;
|
||||||
|
public:
|
||||||
|
HeapDumpDCmd(outputStream* output, bool heap);
|
||||||
|
static const char* name() {
|
||||||
|
return "GC.heap_dump";
|
||||||
|
}
|
||||||
|
static const char* description() {
|
||||||
|
return "Generate a HPROF format dump of the Java heap.";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "High: Depends on Java heap size and content. "
|
||||||
|
"Request a full GC unless the '-all' option is specified.";
|
||||||
|
}
|
||||||
|
static int num_arguments();
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
#endif // SERVICES_KERNEL
|
||||||
|
|
||||||
|
// See also: inspeactheap in attachListener.cpp
|
||||||
|
class ClassHistogramDCmd : public DCmdWithParser {
|
||||||
|
protected:
|
||||||
|
DCmdArgument<bool> _all;
|
||||||
|
public:
|
||||||
|
ClassHistogramDCmd(outputStream* output, bool heap);
|
||||||
|
static const char* name() {
|
||||||
|
return "GC.class_histogram";
|
||||||
|
}
|
||||||
|
static const char* description() {
|
||||||
|
return "Provide statistics about the Java heap usage.";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "High: Depends on Java heap size and content.";
|
||||||
|
}
|
||||||
|
static int num_arguments();
|
||||||
|
virtual void execute(TRAPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
// See also: thread_dump in attachListener.cpp
|
||||||
|
class ThreadDumpDCmd : public DCmdWithParser {
|
||||||
|
protected:
|
||||||
|
DCmdArgument<bool> _locks;
|
||||||
|
public:
|
||||||
|
ThreadDumpDCmd(outputStream* output, bool heap);
|
||||||
|
static const char* name() { return "Thread.print"; }
|
||||||
|
static const char* description() {
|
||||||
|
return "Print all threads with stacktraces.";
|
||||||
|
}
|
||||||
|
static const char* impact() {
|
||||||
|
return "Medium: Depends on the number of threads.";
|
||||||
|
}
|
||||||
|
static int num_arguments();
|
||||||
|
virtual void execute(TRAPS);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
|
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
|
||||||
|
@ -226,7 +226,7 @@ void DCmdParser::check(TRAPS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DCmdParser::print_help(outputStream* out, const char* cmd_name) {
|
void DCmdParser::print_help(outputStream* out, const char* cmd_name) {
|
||||||
out->print("\nSyntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
|
out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
|
||||||
GenDCmdArgument* arg = _arguments_list;
|
GenDCmdArgument* arg = _arguments_list;
|
||||||
while (arg != NULL) {
|
while (arg != NULL) {
|
||||||
if (arg->is_mandatory()) {
|
if (arg->is_mandatory()) {
|
||||||
@ -373,6 +373,30 @@ void DCmd::parse_and_execute(outputStream* out, const char* cmdline,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
|
||||||
|
_dcmdparser.parse(line, delim, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCmdWithParser::print_help(const char* name) {
|
||||||
|
_dcmdparser.print_help(output(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCmdWithParser::reset(TRAPS) {
|
||||||
|
_dcmdparser.reset(CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCmdWithParser::cleanup() {
|
||||||
|
_dcmdparser.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
GrowableArray<const char*>* DCmdWithParser::argument_name_array() {
|
||||||
|
return _dcmdparser.argument_name_array();
|
||||||
|
}
|
||||||
|
|
||||||
|
GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() {
|
||||||
|
return _dcmdparser.argument_info_array();
|
||||||
|
}
|
||||||
|
|
||||||
Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true);
|
Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true);
|
||||||
|
|
||||||
DCmdFactory* DCmdFactory::factory(const char* name, size_t len) {
|
DCmdFactory* DCmdFactory::factory(const char* name, size_t len) {
|
||||||
|
@ -241,8 +241,17 @@ public:
|
|||||||
static int num_arguments() { return 0; }
|
static int num_arguments() { return 0; }
|
||||||
outputStream* output() { return _output; }
|
outputStream* output() { return _output; }
|
||||||
bool is_heap_allocated() { return _is_heap_allocated; }
|
bool is_heap_allocated() { return _is_heap_allocated; }
|
||||||
virtual void print_help(outputStream* out) { };
|
virtual void print_help(const char* name) {
|
||||||
virtual void parse(CmdLine* line, char delim, TRAPS) { }
|
output()->print_cr("Syntax: %s", name);
|
||||||
|
}
|
||||||
|
virtual void parse(CmdLine* line, char delim, TRAPS) {
|
||||||
|
DCmdArgIter iter(line->args_addr(), line->args_len(), delim);
|
||||||
|
bool has_arg = iter.next(CHECK);
|
||||||
|
if (has_arg) {
|
||||||
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||||
|
"Unknown argument in diagnostic command");
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void execute(TRAPS) { }
|
virtual void execute(TRAPS) { }
|
||||||
virtual void reset(TRAPS) { }
|
virtual void reset(TRAPS) { }
|
||||||
virtual void cleanup() { }
|
virtual void cleanup() { }
|
||||||
@ -262,6 +271,25 @@ public:
|
|||||||
char delim, TRAPS);
|
char delim, TRAPS);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DCmdWithParser : public DCmd {
|
||||||
|
protected:
|
||||||
|
DCmdParser _dcmdparser;
|
||||||
|
public:
|
||||||
|
DCmdWithParser (outputStream *output, bool heap=false) : DCmd(output, heap) { }
|
||||||
|
static const char* name() { return "No Name";}
|
||||||
|
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 int num_arguments() { return 0; }
|
||||||
|
virtual void parse(CmdLine *line, char delim, TRAPS);
|
||||||
|
virtual void execute(TRAPS) { }
|
||||||
|
virtual void reset(TRAPS);
|
||||||
|
virtual void cleanup();
|
||||||
|
virtual void print_help(const char* name);
|
||||||
|
virtual GrowableArray<const char*>* argument_name_array();
|
||||||
|
virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array();
|
||||||
|
};
|
||||||
|
|
||||||
class DCmdMark : public StackObj {
|
class DCmdMark : public StackObj {
|
||||||
DCmd* _ref;
|
DCmd* _ref;
|
||||||
public:
|
public:
|
||||||
|
@ -118,8 +118,22 @@ void Management::init() {
|
|||||||
#endif // SERVICES_KERNEL
|
#endif // SERVICES_KERNEL
|
||||||
_optional_support.isThreadAllocatedMemorySupported = 1;
|
_optional_support.isThreadAllocatedMemorySupported = 1;
|
||||||
|
|
||||||
|
// 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<HelpDCmd>(true, false));
|
||||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(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));
|
||||||
|
#ifndef SERVICES_KERNEL // Heap dumping not supported
|
||||||
|
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(true, false));
|
||||||
|
#endif // SERVICES_KERNEL
|
||||||
|
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
|
||||||
|
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Management::initialize(TRAPS) {
|
void Management::initialize(TRAPS) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user