Mon, 09 Jan 2012 10:27:24 +0100
7120511: Add diagnostic commands
Reviewed-by: acorn, phh, dcubed, sspitsyn
1.1 --- a/src/share/vm/classfile/vmSymbols.hpp Thu Jan 05 17:16:13 2012 -0500 1.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Jan 09 10:27:24 2012 +0100 1.3 @@ -296,6 +296,7 @@ 1.4 template(finalize_method_name, "finalize") \ 1.5 template(reference_lock_name, "lock") \ 1.6 template(reference_discovered_name, "discovered") \ 1.7 + template(run_finalization_name, "runFinalization") \ 1.8 template(run_finalizers_on_exit_name, "runFinalizersOnExit") \ 1.9 template(uncaughtException_name, "uncaughtException") \ 1.10 template(dispatchUncaughtException_name, "dispatchUncaughtException") \
2.1 --- a/src/share/vm/runtime/arguments.cpp Thu Jan 05 17:16:13 2012 -0500 2.2 +++ b/src/share/vm/runtime/arguments.cpp Mon Jan 09 10:27:24 2012 +0100 2.3 @@ -2323,7 +2323,7 @@ 2.4 #ifndef PRODUCT 2.5 // -Xprintflags 2.6 } else if (match_option(option, "-Xprintflags", &tail)) { 2.7 - CommandLineFlags::printFlags(); 2.8 + CommandLineFlags::printFlags(tty, false); 2.9 vm_exit(0); 2.10 #endif 2.11 // -D 2.12 @@ -2971,13 +2971,13 @@ 2.13 IgnoreUnrecognizedVMOptions = false; 2.14 } 2.15 if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) { 2.16 - CommandLineFlags::printFlags(); 2.17 + CommandLineFlags::printFlags(tty, false); 2.18 vm_exit(0); 2.19 } 2.20 2.21 #ifndef PRODUCT 2.22 if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) { 2.23 - CommandLineFlags::printFlags(true); 2.24 + CommandLineFlags::printFlags(tty, true); 2.25 vm_exit(0); 2.26 } 2.27 #endif 2.28 @@ -3170,7 +3170,7 @@ 2.29 #endif 2.30 2.31 if (PrintCommandLineFlags) { 2.32 - CommandLineFlags::printSetFlags(); 2.33 + CommandLineFlags::printSetFlags(tty); 2.34 } 2.35 2.36 // Apply CPU specific policy for the BiasedLocking
3.1 --- a/src/share/vm/runtime/globals.cpp Thu Jan 05 17:16:13 2012 -0500 3.2 +++ b/src/share/vm/runtime/globals.cpp Mon Jan 09 10:27:24 2012 +0100 3.3 @@ -488,7 +488,7 @@ 3.4 } 3.5 } 3.6 3.7 -void CommandLineFlags::printSetFlags() { 3.8 +void CommandLineFlags::printSetFlags(outputStream* out) { 3.9 // Print which flags were set on the command line 3.10 // note: this method is called before the thread structure is in place 3.11 // which means resource allocation cannot be used. 3.12 @@ -507,11 +507,11 @@ 3.13 // Print 3.14 for (int i = 0; i < length; i++) { 3.15 if (array[i]->origin /* naked field! */) { 3.16 - array[i]->print_as_flag(tty); 3.17 - tty->print(" "); 3.18 + array[i]->print_as_flag(out); 3.19 + out->print(" "); 3.20 } 3.21 } 3.22 - tty->cr(); 3.23 + out->cr(); 3.24 FREE_C_HEAP_ARRAY(Flag*, array); 3.25 } 3.26 3.27 @@ -524,7 +524,7 @@ 3.28 3.29 #endif // PRODUCT 3.30 3.31 -void CommandLineFlags::printFlags(bool withComments) { 3.32 +void CommandLineFlags::printFlags(outputStream* out, bool withComments) { 3.33 // Print the flags sorted by name 3.34 // note: this method is called before the thread structure is in place 3.35 // which means resource allocation cannot be used. 3.36 @@ -541,10 +541,10 @@ 3.37 qsort(array, length, sizeof(Flag*), compare_flags); 3.38 3.39 // Print 3.40 - tty->print_cr("[Global flags]"); 3.41 + out->print_cr("[Global flags]"); 3.42 for (int i = 0; i < length; i++) { 3.43 if (array[i]->is_unlocked()) { 3.44 - array[i]->print_on(tty, withComments); 3.45 + array[i]->print_on(out, withComments); 3.46 } 3.47 } 3.48 FREE_C_HEAP_ARRAY(Flag*, array);
4.1 --- a/src/share/vm/runtime/globals.hpp Thu Jan 05 17:16:13 2012 -0500 4.2 +++ b/src/share/vm/runtime/globals.hpp Mon Jan 09 10:27:24 2012 +0100 4.3 @@ -326,9 +326,9 @@ 4.4 4.5 // Returns false if name is not a command line flag. 4.6 static bool wasSetOnCmdline(const char* name, bool* value); 4.7 - static void printSetFlags(); 4.8 + static void printSetFlags(outputStream* out); 4.9 4.10 - static void printFlags(bool withComments = false ); 4.11 + static void printFlags(outputStream* out, bool withComments); 4.12 4.13 static void verify() PRODUCT_RETURN; 4.14 };
5.1 --- a/src/share/vm/runtime/init.cpp Thu Jan 05 17:16:13 2012 -0500 5.2 +++ b/src/share/vm/runtime/init.cpp Mon Jan 09 10:27:24 2012 +0100 5.3 @@ -140,7 +140,7 @@ 5.4 // All the flags that get adjusted by VM_Version_init and os::init_2 5.5 // have been set so dump the flags now. 5.6 if (PrintFlagsFinal) { 5.7 - CommandLineFlags::printFlags(); 5.8 + CommandLineFlags::printFlags(tty, false); 5.9 } 5.10 5.11 return JNI_OK;
6.1 --- a/src/share/vm/services/attachListener.cpp Thu Jan 05 17:16:13 2012 -0500 6.2 +++ b/src/share/vm/services/attachListener.cpp Mon Jan 09 10:27:24 2012 +0100 6.3 @@ -99,6 +99,7 @@ 6.4 } 6.5 6.6 // Implementation of "properties" command. 6.7 +// See also: PrintSystemPropertiesDCmd class 6.8 static jint get_system_properties(AttachOperation* op, outputStream* out) { 6.9 return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name()); 6.10 } 6.11 @@ -127,6 +128,7 @@ 6.12 } 6.13 6.14 // Implementation of "threaddump" command - essentially a remote ctrl-break 6.15 +// See also: ThreadDumpDCmd class 6.16 // 6.17 static jint thread_dump(AttachOperation* op, outputStream* out) { 6.18 bool print_concurrent_locks = false; 6.19 @@ -158,6 +160,7 @@ 6.20 DCmd::parse_and_execute(out, op->arg(0), ' ', THREAD); 6.21 if (HAS_PENDING_EXCEPTION) { 6.22 java_lang_Throwable::print(PENDING_EXCEPTION, out); 6.23 + out->cr(); 6.24 CLEAR_PENDING_EXCEPTION; 6.25 // The exception has been printed on the output stream 6.26 // If the JVM returns JNI_ERR, the attachAPI throws a generic I/O 6.27 @@ -169,6 +172,7 @@ 6.28 6.29 #ifndef SERVICES_KERNEL // Heap dumping not supported 6.30 // Implementation of "dumpheap" command. 6.31 +// See also: HeapDumpDCmd class 6.32 // 6.33 // Input arguments :- 6.34 // arg0: Name of the dump file 6.35 @@ -211,6 +215,7 @@ 6.36 #endif // SERVICES_KERNEL 6.37 6.38 // Implementation of "inspectheap" command 6.39 +// See also: ClassHistogramDCmd class 6.40 // 6.41 // Input arguments :- 6.42 // arg0: "-live" or "-all" 6.43 @@ -354,6 +359,7 @@ 6.44 } 6.45 6.46 // Implementation of "printflag" command 6.47 +// See also: PrintVMFlagsDCmd class 6.48 static jint print_flag(AttachOperation* op, outputStream* out) { 6.49 const char* name = NULL; 6.50 if ((name = op->arg(0)) == NULL) {
7.1 --- a/src/share/vm/services/diagnosticCommand.cpp Thu Jan 05 17:16:13 2012 -0500 7.2 +++ b/src/share/vm/services/diagnosticCommand.cpp Mon Jan 09 10:27:24 2012 +0100 7.3 @@ -23,11 +23,15 @@ 7.4 */ 7.5 7.6 #include "precompiled.hpp" 7.7 +#include "gc_implementation/shared/vmGCOperations.hpp" 7.8 +#include "runtime/javaCalls.hpp" 7.9 #include "services/diagnosticArgument.hpp" 7.10 #include "services/diagnosticCommand.hpp" 7.11 #include "services/diagnosticFramework.hpp" 7.12 +#include "services/heapDumper.hpp" 7.13 +#include "services/management.hpp" 7.14 7.15 -HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmd(output, heap), 7.16 +HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), 7.17 _all("-all", "Show help for all commands", "BOOLEAN", false, "false"), 7.18 _cmd("command name", "The name of the command for which we want help", 7.19 "STRING", false) { 7.20 @@ -35,14 +39,6 @@ 7.21 _dcmdparser.add_dcmd_argument(&_cmd); 7.22 }; 7.23 7.24 -void HelpDCmd::parse(CmdLine* line, char delim, TRAPS) { 7.25 - _dcmdparser.parse(line, delim, CHECK); 7.26 -} 7.27 - 7.28 -void HelpDCmd::print_help(outputStream* out) { 7.29 - _dcmdparser.print_help(out, name()); 7.30 -} 7.31 - 7.32 void HelpDCmd::execute(TRAPS) { 7.33 if (_all.value()) { 7.34 GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(); 7.35 @@ -66,10 +62,11 @@ 7.36 factory->is_enabled() ? "" : " [disabled]"); 7.37 output()->print_cr(factory->description()); 7.38 output()->print_cr("\nImpact: %s", factory->impact()); 7.39 + output()->cr(); 7.40 cmd = factory->create_resource_instance(output()); 7.41 if (cmd != NULL) { 7.42 DCmdMark mark(cmd); 7.43 - cmd->print_help(output()); 7.44 + cmd->print_help(factory->name()); 7.45 } 7.46 } else { 7.47 output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value()); 7.48 @@ -90,14 +87,6 @@ 7.49 } 7.50 } 7.51 7.52 -void HelpDCmd::reset(TRAPS) { 7.53 - _dcmdparser.reset(CHECK); 7.54 -} 7.55 - 7.56 -void HelpDCmd::cleanup() { 7.57 - _dcmdparser.cleanup(); 7.58 -} 7.59 - 7.60 int HelpDCmd::num_arguments() { 7.61 ResourceMark rm; 7.62 HelpDCmd* dcmd = new HelpDCmd(NULL, false); 7.63 @@ -109,14 +98,6 @@ 7.64 } 7.65 } 7.66 7.67 -GrowableArray<const char*>* HelpDCmd::argument_name_array() { 7.68 - return _dcmdparser.argument_name_array(); 7.69 -} 7.70 - 7.71 -GrowableArray<DCmdArgumentInfo*>* HelpDCmd::argument_info_array() { 7.72 - return _dcmdparser.argument_info_array(); 7.73 -} 7.74 - 7.75 void VersionDCmd::execute(TRAPS) { 7.76 output()->print_cr("%s version %s", Abstract_VM_Version::vm_name(), 7.77 Abstract_VM_Version::vm_release()); 7.78 @@ -129,3 +110,210 @@ 7.79 jdk_version.minor_version()); 7.80 } 7.81 } 7.82 + 7.83 +PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) : 7.84 + DCmdWithParser(output, heap), 7.85 + _all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") { 7.86 + _dcmdparser.add_dcmd_option(&_all); 7.87 +} 7.88 + 7.89 +void PrintVMFlagsDCmd::execute(TRAPS) { 7.90 + if (_all.value()) { 7.91 + CommandLineFlags::printFlags(output(), true); 7.92 + } else { 7.93 + CommandLineFlags::printSetFlags(output()); 7.94 + } 7.95 +} 7.96 + 7.97 +int PrintVMFlagsDCmd::num_arguments() { 7.98 + ResourceMark rm; 7.99 + PrintVMFlagsDCmd* dcmd = new PrintVMFlagsDCmd(NULL, false); 7.100 + if (dcmd != NULL) { 7.101 + DCmdMark mark(dcmd); 7.102 + return dcmd->_dcmdparser.num_arguments(); 7.103 + } else { 7.104 + return 0; 7.105 + } 7.106 +} 7.107 + 7.108 +void PrintSystemPropertiesDCmd::execute(TRAPS) { 7.109 + // load sun.misc.VMSupport 7.110 + Symbol* klass = vmSymbols::sun_misc_VMSupport(); 7.111 + klassOop k = SystemDictionary::resolve_or_fail(klass, true, CHECK); 7.112 + instanceKlassHandle ik (THREAD, k); 7.113 + if (ik->should_be_initialized()) { 7.114 + ik->initialize(THREAD); 7.115 + } 7.116 + if (HAS_PENDING_EXCEPTION) { 7.117 + java_lang_Throwable::print(PENDING_EXCEPTION, output()); 7.118 + output()->cr(); 7.119 + CLEAR_PENDING_EXCEPTION; 7.120 + return; 7.121 + } 7.122 + 7.123 + // invoke the serializePropertiesToByteArray method 7.124 + JavaValue result(T_OBJECT); 7.125 + JavaCallArguments args; 7.126 + 7.127 + Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature(); 7.128 + JavaCalls::call_static(&result, 7.129 + ik, 7.130 + vmSymbols::serializePropertiesToByteArray_name(), 7.131 + signature, 7.132 + &args, 7.133 + THREAD); 7.134 + if (HAS_PENDING_EXCEPTION) { 7.135 + java_lang_Throwable::print(PENDING_EXCEPTION, output()); 7.136 + output()->cr(); 7.137 + CLEAR_PENDING_EXCEPTION; 7.138 + return; 7.139 + } 7.140 + 7.141 + // The result should be a [B 7.142 + oop res = (oop)result.get_jobject(); 7.143 + assert(res->is_typeArray(), "just checking"); 7.144 + assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking"); 7.145 + 7.146 + // copy the bytes to the output stream 7.147 + typeArrayOop ba = typeArrayOop(res); 7.148 + jbyte* addr = typeArrayOop(res)->byte_at_addr(0); 7.149 + output()->print_raw((const char*)addr, ba->length()); 7.150 +} 7.151 + 7.152 +VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) : 7.153 + DCmdWithParser(output, heap), 7.154 + _date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") { 7.155 + _dcmdparser.add_dcmd_option(&_date); 7.156 +} 7.157 + 7.158 +void VMUptimeDCmd::execute(TRAPS) { 7.159 + if (_date.value()) { 7.160 + output()->date_stamp(true, "", ": "); 7.161 + } 7.162 + output()->time_stamp().update_to(tty->time_stamp().ticks()); 7.163 + output()->stamp(); 7.164 + output()->print_cr(" s"); 7.165 +} 7.166 + 7.167 +int VMUptimeDCmd::num_arguments() { 7.168 + ResourceMark rm; 7.169 + VMUptimeDCmd* dcmd = new VMUptimeDCmd(NULL, false); 7.170 + if (dcmd != NULL) { 7.171 + DCmdMark mark(dcmd); 7.172 + return dcmd->_dcmdparser.num_arguments(); 7.173 + } else { 7.174 + return 0; 7.175 + } 7.176 +} 7.177 + 7.178 +void SystemGCDCmd::execute(TRAPS) { 7.179 + Universe::heap()->collect(GCCause::_java_lang_system_gc); 7.180 +} 7.181 + 7.182 +void RunFinalizationDCmd::execute(TRAPS) { 7.183 + klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), 7.184 + true, CHECK); 7.185 + instanceKlassHandle klass(THREAD, k); 7.186 + JavaValue result(T_VOID); 7.187 + JavaCalls::call_static(&result, klass, 7.188 + vmSymbols::run_finalization_name(), 7.189 + vmSymbols::void_method_signature(), CHECK); 7.190 +} 7.191 + 7.192 +#ifndef SERVICES_KERNEL // Heap dumping not supported 7.193 +HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : 7.194 + DCmdWithParser(output, heap), 7.195 + _filename("filename","Name of the dump file", "STRING",true), 7.196 + _all("-all", "Dump all objects, including unreachable objects", 7.197 + "BOOLEAN", false, "false") { 7.198 + _dcmdparser.add_dcmd_option(&_all); 7.199 + _dcmdparser.add_dcmd_argument(&_filename); 7.200 +} 7.201 + 7.202 +void HeapDumpDCmd::execute(TRAPS) { 7.203 + // Request a full GC before heap dump if _all is false 7.204 + // This helps reduces the amount of unreachable objects in the dump 7.205 + // and makes it easier to browse. 7.206 + HeapDumper dumper(!_all.value() /* request GC if _all is false*/); 7.207 + int res = dumper.dump(_filename.value()); 7.208 + if (res == 0) { 7.209 + output()->print_cr("Heap dump file created"); 7.210 + } else { 7.211 + // heap dump failed 7.212 + ResourceMark rm; 7.213 + char* error = dumper.error_as_C_string(); 7.214 + if (error == NULL) { 7.215 + output()->print_cr("Dump failed - reason unknown"); 7.216 + } else { 7.217 + output()->print_cr("%s", error); 7.218 + } 7.219 + } 7.220 +} 7.221 + 7.222 +int HeapDumpDCmd::num_arguments() { 7.223 + ResourceMark rm; 7.224 + HeapDumpDCmd* dcmd = new HeapDumpDCmd(NULL, false); 7.225 + if (dcmd != NULL) { 7.226 + DCmdMark mark(dcmd); 7.227 + return dcmd->_dcmdparser.num_arguments(); 7.228 + } else { 7.229 + return 0; 7.230 + } 7.231 +} 7.232 +#endif // SERVICES_KERNEL 7.233 + 7.234 +ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) : 7.235 + DCmdWithParser(output, heap), 7.236 + _all("-all", "Inspect all objects, including unreachable objects", 7.237 + "BOOLEAN", false, "false") { 7.238 + _dcmdparser.add_dcmd_option(&_all); 7.239 +} 7.240 + 7.241 +void ClassHistogramDCmd::execute(TRAPS) { 7.242 + VM_GC_HeapInspection heapop(output(), 7.243 + !_all.value() /* request full gc if false */, 7.244 + true /* need_prologue */); 7.245 + VMThread::execute(&heapop); 7.246 +} 7.247 + 7.248 +int ClassHistogramDCmd::num_arguments() { 7.249 + ResourceMark rm; 7.250 + ClassHistogramDCmd* dcmd = new ClassHistogramDCmd(NULL, false); 7.251 + if (dcmd != NULL) { 7.252 + DCmdMark mark(dcmd); 7.253 + return dcmd->_dcmdparser.num_arguments(); 7.254 + } else { 7.255 + return 0; 7.256 + } 7.257 +} 7.258 + 7.259 +ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) : 7.260 + DCmdWithParser(output, heap), 7.261 + _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") { 7.262 + _dcmdparser.add_dcmd_option(&_locks); 7.263 +} 7.264 + 7.265 +void ThreadDumpDCmd::execute(TRAPS) { 7.266 + // thread stacks 7.267 + VM_PrintThreads op1(output(), _locks.value()); 7.268 + VMThread::execute(&op1); 7.269 + 7.270 + // JNI global handles 7.271 + VM_PrintJNI op2(output()); 7.272 + VMThread::execute(&op2); 7.273 + 7.274 + // Deadlock detection 7.275 + VM_FindDeadlocks op3(output()); 7.276 + VMThread::execute(&op3); 7.277 +} 7.278 + 7.279 +int ThreadDumpDCmd::num_arguments() { 7.280 + ResourceMark rm; 7.281 + ThreadDumpDCmd* dcmd = new ThreadDumpDCmd(NULL, false); 7.282 + if (dcmd != NULL) { 7.283 + DCmdMark mark(dcmd); 7.284 + return dcmd->_dcmdparser.num_arguments(); 7.285 + } else { 7.286 + return 0; 7.287 + } 7.288 +}
8.1 --- a/src/share/vm/services/diagnosticCommand.hpp Thu Jan 05 17:16:13 2012 -0500 8.2 +++ b/src/share/vm/services/diagnosticCommand.hpp Mon Jan 09 10:27:24 2012 +0100 8.3 @@ -35,9 +35,8 @@ 8.4 #include "services/diagnosticCommand.hpp" 8.5 #include "services/diagnosticFramework.hpp" 8.6 8.7 -class HelpDCmd : public DCmd { 8.8 +class HelpDCmd : public DCmdWithParser { 8.9 protected: 8.10 - DCmdParser _dcmdparser; 8.11 DCmdArgument<bool> _all; 8.12 DCmdArgument<char*> _cmd; 8.13 public: 8.14 @@ -50,13 +49,7 @@ 8.15 } 8.16 static const char* impact() { return "Low: "; } 8.17 static int num_arguments(); 8.18 - virtual void parse(CmdLine* line, char delim, TRAPS); 8.19 virtual void execute(TRAPS); 8.20 - virtual void reset(TRAPS); 8.21 - virtual void cleanup(); 8.22 - virtual void print_help(outputStream* out); 8.23 - virtual GrowableArray<const char*>* argument_name_array(); 8.24 - virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array(); 8.25 }; 8.26 8.27 class VersionDCmd : public DCmd { 8.28 @@ -68,9 +61,156 @@ 8.29 } 8.30 static const char* impact() { return "Low: "; } 8.31 static int num_arguments() { return 0; } 8.32 - virtual void parse(CmdLine* line, char delim, TRAPS) { } 8.33 virtual void execute(TRAPS); 8.34 - virtual void print_help(outputStream* out) { } 8.35 +}; 8.36 + 8.37 +class CommandLineDCmd : public DCmd { 8.38 +public: 8.39 + CommandLineDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 8.40 + static const char* name() { return "VM.command_line"; } 8.41 + static const char* description() { 8.42 + return "Print the command line used to start this VM instance."; 8.43 + } 8.44 + static const char* impact() { return "Low: "; } 8.45 + static int num_arguments() { return 0; } 8.46 + virtual void execute(TRAPS) { 8.47 + Arguments::print_on(_output); 8.48 + } 8.49 +}; 8.50 + 8.51 +// See also: get_system_properties in attachListener.cpp 8.52 +class PrintSystemPropertiesDCmd : public DCmd { 8.53 +public: 8.54 + PrintSystemPropertiesDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 8.55 + static const char* name() { return "VM.system_properties"; } 8.56 + static const char* description() { 8.57 + return "Print system properties."; 8.58 + } 8.59 + static const char* impact() { 8.60 + return "Low: "; 8.61 + } 8.62 + static int num_arguments() { return 0; } 8.63 + virtual void execute(TRAPS); 8.64 +}; 8.65 + 8.66 +// See also: print_flag in attachListener.cpp 8.67 +class PrintVMFlagsDCmd : public DCmdWithParser { 8.68 +protected: 8.69 + DCmdArgument<bool> _all; 8.70 +public: 8.71 + PrintVMFlagsDCmd(outputStream* output, bool heap); 8.72 + static const char* name() { return "VM.flags"; } 8.73 + static const char* description() { 8.74 + return "Print VM flag options and their current values."; 8.75 + } 8.76 + static const char* impact() { 8.77 + return "Low: "; 8.78 + } 8.79 + static int num_arguments(); 8.80 + virtual void execute(TRAPS); 8.81 +}; 8.82 + 8.83 +class VMUptimeDCmd : public DCmdWithParser { 8.84 +protected: 8.85 + DCmdArgument<bool> _date; 8.86 +public: 8.87 + VMUptimeDCmd(outputStream* output, bool heap); 8.88 + static const char* name() { return "VM.uptime"; } 8.89 + static const char* description() { 8.90 + return "Print VM uptime."; 8.91 + } 8.92 + static const char* impact() { 8.93 + return "Low: "; 8.94 + } 8.95 + static int num_arguments(); 8.96 + virtual void execute(TRAPS); 8.97 +}; 8.98 + 8.99 +class SystemGCDCmd : public DCmd { 8.100 +public: 8.101 + SystemGCDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 8.102 + static const char* name() { return "GC.run"; } 8.103 + static const char* description() { 8.104 + return "Call java.lang.System.gc()."; 8.105 + } 8.106 + static const char* impact() { 8.107 + return "Medium: Depends on Java heap size and content."; 8.108 + } 8.109 + static int num_arguments() { return 0; } 8.110 + virtual void execute(TRAPS); 8.111 +}; 8.112 + 8.113 +class RunFinalizationDCmd : public DCmd { 8.114 +public: 8.115 + RunFinalizationDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 8.116 + static const char* name() { return "GC.run_finalization"; } 8.117 + static const char* description() { 8.118 + return "Call java.lang.System.runFinalization()."; 8.119 + } 8.120 + static const char* impact() { 8.121 + return "Medium: Depends on Java content."; 8.122 + } 8.123 + static int num_arguments() { return 0; } 8.124 + virtual void execute(TRAPS); 8.125 +}; 8.126 + 8.127 +#ifndef SERVICES_KERNEL // Heap dumping not supported 8.128 +// See also: dump_heap in attachListener.cpp 8.129 +class HeapDumpDCmd : public DCmdWithParser { 8.130 +protected: 8.131 + DCmdArgument<char*> _filename; 8.132 + DCmdArgument<bool> _all; 8.133 +public: 8.134 + HeapDumpDCmd(outputStream* output, bool heap); 8.135 + static const char* name() { 8.136 + return "GC.heap_dump"; 8.137 + } 8.138 + static const char* description() { 8.139 + return "Generate a HPROF format dump of the Java heap."; 8.140 + } 8.141 + static const char* impact() { 8.142 + return "High: Depends on Java heap size and content. " 8.143 + "Request a full GC unless the '-all' option is specified."; 8.144 + } 8.145 + static int num_arguments(); 8.146 + virtual void execute(TRAPS); 8.147 +}; 8.148 +#endif // SERVICES_KERNEL 8.149 + 8.150 +// See also: inspeactheap in attachListener.cpp 8.151 +class ClassHistogramDCmd : public DCmdWithParser { 8.152 +protected: 8.153 + DCmdArgument<bool> _all; 8.154 +public: 8.155 + ClassHistogramDCmd(outputStream* output, bool heap); 8.156 + static const char* name() { 8.157 + return "GC.class_histogram"; 8.158 + } 8.159 + static const char* description() { 8.160 + return "Provide statistics about the Java heap usage."; 8.161 + } 8.162 + static const char* impact() { 8.163 + return "High: Depends on Java heap size and content."; 8.164 + } 8.165 + static int num_arguments(); 8.166 + virtual void execute(TRAPS); 8.167 +}; 8.168 + 8.169 +// See also: thread_dump in attachListener.cpp 8.170 +class ThreadDumpDCmd : public DCmdWithParser { 8.171 +protected: 8.172 + DCmdArgument<bool> _locks; 8.173 +public: 8.174 + ThreadDumpDCmd(outputStream* output, bool heap); 8.175 + static const char* name() { return "Thread.print"; } 8.176 + static const char* description() { 8.177 + return "Print all threads with stacktraces."; 8.178 + } 8.179 + static const char* impact() { 8.180 + return "Medium: Depends on the number of threads."; 8.181 + } 8.182 + static int num_arguments(); 8.183 + virtual void execute(TRAPS); 8.184 }; 8.185 8.186 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
9.1 --- a/src/share/vm/services/diagnosticFramework.cpp Thu Jan 05 17:16:13 2012 -0500 9.2 +++ b/src/share/vm/services/diagnosticFramework.cpp Mon Jan 09 10:27:24 2012 +0100 9.3 @@ -226,7 +226,7 @@ 9.4 } 9.5 9.6 void DCmdParser::print_help(outputStream* out, const char* cmd_name) { 9.7 - out->print("\nSyntax : %s %s", cmd_name, _options == NULL ? "" : "[options]"); 9.8 + out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]"); 9.9 GenDCmdArgument* arg = _arguments_list; 9.10 while (arg != NULL) { 9.11 if (arg->is_mandatory()) { 9.12 @@ -373,6 +373,30 @@ 9.13 } 9.14 } 9.15 9.16 +void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) { 9.17 + _dcmdparser.parse(line, delim, CHECK); 9.18 +} 9.19 + 9.20 +void DCmdWithParser::print_help(const char* name) { 9.21 + _dcmdparser.print_help(output(), name); 9.22 +} 9.23 + 9.24 +void DCmdWithParser::reset(TRAPS) { 9.25 + _dcmdparser.reset(CHECK); 9.26 +} 9.27 + 9.28 +void DCmdWithParser::cleanup() { 9.29 + _dcmdparser.cleanup(); 9.30 +} 9.31 + 9.32 +GrowableArray<const char*>* DCmdWithParser::argument_name_array() { 9.33 + return _dcmdparser.argument_name_array(); 9.34 +} 9.35 + 9.36 +GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() { 9.37 + return _dcmdparser.argument_info_array(); 9.38 +} 9.39 + 9.40 Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true); 9.41 9.42 DCmdFactory* DCmdFactory::factory(const char* name, size_t len) {
10.1 --- a/src/share/vm/services/diagnosticFramework.hpp Thu Jan 05 17:16:13 2012 -0500 10.2 +++ b/src/share/vm/services/diagnosticFramework.hpp Mon Jan 09 10:27:24 2012 +0100 10.3 @@ -241,8 +241,17 @@ 10.4 static int num_arguments() { return 0; } 10.5 outputStream* output() { return _output; } 10.6 bool is_heap_allocated() { return _is_heap_allocated; } 10.7 - virtual void print_help(outputStream* out) { }; 10.8 - virtual void parse(CmdLine* line, char delim, TRAPS) { } 10.9 + virtual void print_help(const char* name) { 10.10 + output()->print_cr("Syntax: %s", name); 10.11 + } 10.12 + virtual void parse(CmdLine* line, char delim, TRAPS) { 10.13 + DCmdArgIter iter(line->args_addr(), line->args_len(), delim); 10.14 + bool has_arg = iter.next(CHECK); 10.15 + if (has_arg) { 10.16 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 10.17 + "Unknown argument in diagnostic command"); 10.18 + } 10.19 + } 10.20 virtual void execute(TRAPS) { } 10.21 virtual void reset(TRAPS) { } 10.22 virtual void cleanup() { } 10.23 @@ -262,6 +271,25 @@ 10.24 char delim, TRAPS); 10.25 }; 10.26 10.27 +class DCmdWithParser : public DCmd { 10.28 +protected: 10.29 + DCmdParser _dcmdparser; 10.30 +public: 10.31 + DCmdWithParser (outputStream *output, bool heap=false) : DCmd(output, heap) { } 10.32 + static const char* name() { return "No Name";} 10.33 + static const char* description() { return "No Help";} 10.34 + static const char* disabled_message() { return "Diagnostic command currently disabled"; } 10.35 + static const char* impact() { return "Low: No impact"; } 10.36 + static int num_arguments() { return 0; } 10.37 + virtual void parse(CmdLine *line, char delim, TRAPS); 10.38 + virtual void execute(TRAPS) { } 10.39 + virtual void reset(TRAPS); 10.40 + virtual void cleanup(); 10.41 + virtual void print_help(const char* name); 10.42 + virtual GrowableArray<const char*>* argument_name_array(); 10.43 + virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array(); 10.44 +}; 10.45 + 10.46 class DCmdMark : public StackObj { 10.47 DCmd* _ref; 10.48 public:
11.1 --- a/src/share/vm/services/management.cpp Thu Jan 05 17:16:13 2012 -0500 11.2 +++ b/src/share/vm/services/management.cpp Mon Jan 09 10:27:24 2012 +0100 11.3 @@ -118,8 +118,22 @@ 11.4 #endif // SERVICES_KERNEL 11.5 _optional_support.isThreadAllocatedMemorySupported = 1; 11.6 11.7 + // Registration of the diagnostic commands 11.8 + // First boolean argument specifies if the command is enabled 11.9 + // Second boolean argument specifies if the command is hidden 11.10 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(true, false)); 11.11 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(true, false)); 11.12 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(true, false)); 11.13 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(true, false)); 11.14 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(true, false)); 11.15 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(true, false)); 11.16 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(true, false)); 11.17 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(true, false)); 11.18 +#ifndef SERVICES_KERNEL // Heap dumping not supported 11.19 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(true, false)); 11.20 +#endif // SERVICES_KERNEL 11.21 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false)); 11.22 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false)); 11.23 } 11.24 11.25 void Management::initialize(TRAPS) {