From 1f0213d59a1eebc37dc6c815148d7e0fe8fb92df Mon Sep 17 00:00:00 2001 From: Ivan Bereziuk Date: Wed, 14 Jan 2026 12:03:38 +0100 Subject: [PATCH] introduce -T as a commong flag --- src/hotspot/os/linux/mallocInfoDcmd.cpp | 2 +- src/hotspot/os/linux/mallocInfoDcmd.hpp | 2 +- src/hotspot/os/linux/trimCHeapDCmd.cpp | 2 +- src/hotspot/os/linux/trimCHeapDCmd.hpp | 2 +- .../classfile/classLoaderHierarchyDCmd.cpp | 2 +- .../classfile/classLoaderHierarchyDCmd.hpp | 2 +- .../share/classfile/classLoaderStats.cpp | 2 +- .../share/classfile/classLoaderStats.hpp | 2 +- src/hotspot/share/classfile/stringTable.cpp | 2 +- src/hotspot/share/classfile/symbolTable.cpp | 2 +- .../share/classfile/systemDictionary.cpp | 2 +- src/hotspot/share/jfr/dcmd/jfrDcmds.cpp | 4 +- src/hotspot/share/jfr/dcmd/jfrDcmds.hpp | 4 +- .../share/jfr/recorder/jfrRecorder.cpp | 2 +- .../jfr/recorder/service/jfrOptionSet.cpp | 2 +- .../share/logging/logDiagnosticCommand.cpp | 2 +- .../share/logging/logDiagnosticCommand.hpp | 2 +- .../share/memory/metaspace/metaspaceDCmd.cpp | 2 +- .../share/memory/metaspace/metaspaceDCmd.hpp | 2 +- src/hotspot/share/nmt/nmtDCmd.cpp | 2 +- src/hotspot/share/nmt/nmtDCmd.hpp | 2 +- src/hotspot/share/services/attachListener.cpp | 4 +- .../share/services/diagnosticCommand.cpp | 191 ++++++++++++------ .../share/services/diagnosticCommand.hpp | 90 ++++----- .../share/services/diagnosticFramework.cpp | 101 +++++++-- .../share/services/diagnosticFramework.hpp | 20 +- .../classes/sun/tools/jcmd/Arguments.java | 39 +++- 27 files changed, 331 insertions(+), 160 deletions(-) diff --git a/src/hotspot/os/linux/mallocInfoDcmd.cpp b/src/hotspot/os/linux/mallocInfoDcmd.cpp index 1a2368b1e50..80842b7321f 100644 --- a/src/hotspot/os/linux/mallocInfoDcmd.cpp +++ b/src/hotspot/os/linux/mallocInfoDcmd.cpp @@ -32,7 +32,7 @@ constexpr const char* malloc_info_unavailable = "Error: malloc_info(3) not available."; -void MallocInfoDcmd::execute(DCmdSource source, TRAPS) { +void MallocInfoDcmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { #ifdef __GLIBC__ char* buf; size_t size; diff --git a/src/hotspot/os/linux/mallocInfoDcmd.hpp b/src/hotspot/os/linux/mallocInfoDcmd.hpp index f2559fa1571..d50122c8f58 100644 --- a/src/hotspot/os/linux/mallocInfoDcmd.hpp +++ b/src/hotspot/os/linux/mallocInfoDcmd.hpp @@ -41,7 +41,7 @@ public: static const char* impact() { return "Low"; } - void execute(DCmdSource source, TRAPS) override; + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // OS_LINUX_MALLOCINFODCMD_HPP diff --git a/src/hotspot/os/linux/trimCHeapDCmd.cpp b/src/hotspot/os/linux/trimCHeapDCmd.cpp index 6b4cad03c1b..fbe5f4e85ab 100644 --- a/src/hotspot/os/linux/trimCHeapDCmd.cpp +++ b/src/hotspot/os/linux/trimCHeapDCmd.cpp @@ -32,7 +32,7 @@ #include -void TrimCLibcHeapDCmd::execute(DCmdSource source, TRAPS) { +void TrimCLibcHeapDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (os::can_trim_native_heap()) { os::size_change_t sc; if (os::trim_native_heap(&sc)) { diff --git a/src/hotspot/os/linux/trimCHeapDCmd.hpp b/src/hotspot/os/linux/trimCHeapDCmd.hpp index 53b94f4bb56..8f985a85087 100644 --- a/src/hotspot/os/linux/trimCHeapDCmd.hpp +++ b/src/hotspot/os/linux/trimCHeapDCmd.hpp @@ -42,7 +42,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // OS_LINUX_TRIMCHEAPDCMD_HPP diff --git a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp index 2eadb813d7e..19bc286b87f 100644 --- a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp +++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp @@ -547,7 +547,7 @@ public: }; // This command needs to be executed at a safepoint. -void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPS) { +void ClassLoaderHierarchyDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value(), _fold.value()); VMThread::execute(&op); } diff --git a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp index cd89c9cb978..5d4055255a6 100644 --- a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp +++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp @@ -47,7 +47,7 @@ public: return "Medium: Depends on number of class loaders and classes loaded."; } static int num_arguments() { return 3; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; diff --git a/src/hotspot/share/classfile/classLoaderStats.cpp b/src/hotspot/share/classfile/classLoaderStats.cpp index d74e8c1deba..4c23bdb428f 100644 --- a/src/hotspot/share/classfile/classLoaderStats.cpp +++ b/src/hotspot/share/classfile/classLoaderStats.cpp @@ -169,7 +169,7 @@ void ClassLoaderStatsVMOperation::doit() { } -void ClassLoaderStatsDCmd::execute(DCmdSource source, TRAPS) { +void ClassLoaderStatsDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { ClassLoaderStatsVMOperation op(output()); VMThread::execute(&op); } diff --git a/src/hotspot/share/classfile/classLoaderStats.hpp b/src/hotspot/share/classfile/classLoaderStats.hpp index b9b29512ac0..6e82bf8c67f 100644 --- a/src/hotspot/share/classfile/classLoaderStats.hpp +++ b/src/hotspot/share/classfile/classLoaderStats.hpp @@ -51,7 +51,7 @@ public: return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; static int num_arguments() { return 0; diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index c775014cfac..b1ac6882100 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -922,7 +922,7 @@ StringtableDCmd::StringtableDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_verbose); } -void StringtableDCmd::execute(DCmdSource source, TRAPS) { +void StringtableDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings, _verbose.value()); VMThread::execute(&dumper); diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index ec639a2b4d3..c6c01639944 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -954,7 +954,7 @@ SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_verbose); } -void SymboltableDCmd::execute(DCmdSource source, TRAPS) { +void SymboltableDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols, _verbose.value()); VMThread::execute(&dumper); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 0b47c749df8..7dc69fa0155 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -2494,7 +2494,7 @@ SystemDictionaryDCmd::SystemDictionaryDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_verbose); } -void SystemDictionaryDCmd::execute(DCmdSource source, TRAPS) { +void SystemDictionaryDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSysDict, _verbose.value()); VMThread::execute(&dumper); diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 549d879de99..1b364111e0f 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -215,7 +215,7 @@ void JfrDCmd::parse(CmdLine* line, char delim, TRAPS) { // where parse and execute are called consecutively. } -void JfrDCmd::execute(DCmdSource source, TRAPS) { +void JfrDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (invalid_state(output(), THREAD)) { return; } @@ -463,7 +463,7 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(""); } -void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { +void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); if (invalid_state(output(), THREAD)) { diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.hpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.hpp index 8e7dad5a20c..c2567ff46fe 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.hpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.hpp @@ -39,7 +39,7 @@ class JfrDCmd : public DCmd { void invoke(JfrJavaArguments& method, TRAPS) const; void print_java_help(const char* help_method) const; public: - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; virtual void print_help(const char* name) const; virtual GrowableArray* argument_name_array() const; virtual GrowableArray* argument_info_array() const; @@ -202,7 +202,7 @@ class JfrConfigureFlightRecorderDCmd : public DCmdWithParser { return "Low"; } static int num_arguments() { return 10; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; virtual void print_help(const char* name) const; }; diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp index 6a6da0f9b04..d669d1f3932 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp @@ -164,7 +164,7 @@ static bool validate_recording_options(TRAPS) { static bool launch_recording(JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) { assert(dcmd_recording != nullptr, "invariant"); log_trace(jfr, system)("Starting a recording"); - dcmd_recording->execute(DCmd_Source_Internal, THREAD); + dcmd_recording->execute(DCmd_Source_Internal, {}/*commonOptions*/, THREAD); if (HAS_PENDING_EXCEPTION) { log_debug(jfr, system)("Exception while starting a recording"); CLEAR_PENDING_EXCEPTION; diff --git a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp index b212ee4ccba..ada2a390d22 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp @@ -392,7 +392,7 @@ bool JfrOptionSet::configure(TRAPS) { configure._preserve_repository.set_value(_dcmd_preserve_repository.value()); configure.set_verbose(false); - configure.execute(DCmd_Source_Internal, THREAD); + configure.execute(DCmd_Source_Internal, {} /*options*/, THREAD); if (HAS_PENDING_EXCEPTION) { java_lang_Throwable::print(PENDING_EXCEPTION, tty); diff --git a/src/hotspot/share/logging/logDiagnosticCommand.cpp b/src/hotspot/share/logging/logDiagnosticCommand.cpp index c9b1015ab45..2a0783061f6 100644 --- a/src/hotspot/share/logging/logDiagnosticCommand.cpp +++ b/src/hotspot/share/logging/logDiagnosticCommand.cpp @@ -49,7 +49,7 @@ void LogDiagnosticCommand::registerCommand() { DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_visibility)); } -void LogDiagnosticCommand::execute(DCmdSource source, TRAPS) { +void LogDiagnosticCommand::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { bool any_command = false; if (_disable.has_value()) { LogConfiguration::disable_logging(); diff --git a/src/hotspot/share/logging/logDiagnosticCommand.hpp b/src/hotspot/share/logging/logDiagnosticCommand.hpp index a27832306b7..cff7ed7804e 100644 --- a/src/hotspot/share/logging/logDiagnosticCommand.hpp +++ b/src/hotspot/share/logging/logDiagnosticCommand.hpp @@ -47,7 +47,7 @@ class LogDiagnosticCommand : public DCmdWithParser { public: LogDiagnosticCommand(outputStream* output, bool heap_allocated); - void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; static void registerCommand(); static int num_arguments() { return 7; } diff --git a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp index e6943b8e2d3..af635d93d9b 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp @@ -57,7 +57,7 @@ MetaspaceDCmd::MetaspaceDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_scale); } -void MetaspaceDCmd::execute(DCmdSource source, TRAPS) { +void MetaspaceDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { MetaspaceUtils::print_on(output()); // Parse scale value. diff --git a/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp b/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp index 69377057950..141e3d6ca35 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp @@ -53,7 +53,7 @@ public: return "Medium: Depends on number of classes loaded."; } static int num_arguments() { return 8; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; } // namespace metaspace diff --git a/src/hotspot/share/nmt/nmtDCmd.cpp b/src/hotspot/share/nmt/nmtDCmd.cpp index 0c6dc5241a2..2439152e02b 100644 --- a/src/hotspot/share/nmt/nmtDCmd.cpp +++ b/src/hotspot/share/nmt/nmtDCmd.cpp @@ -68,7 +68,7 @@ size_t NMTDCmd::get_scale(const char* scale) const { return NMTUtil::scale_from_name(scale); } -void NMTDCmd::execute(DCmdSource source, TRAPS) { +void NMTDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { // Check NMT state // native memory tracking has to be on if (MemTracker::tracking_level() == NMT_off) { diff --git a/src/hotspot/share/nmt/nmtDCmd.hpp b/src/hotspot/share/nmt/nmtDCmd.hpp index 2a9f9be49bb..b72f00328a7 100644 --- a/src/hotspot/share/nmt/nmtDCmd.hpp +++ b/src/hotspot/share/nmt/nmtDCmd.hpp @@ -53,7 +53,7 @@ class NMTDCmd: public DCmdWithParser { static const char* impact() { return "Medium"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; private: void report(bool summaryOnly, size_t scale); diff --git a/src/hotspot/share/services/attachListener.cpp b/src/hotspot/share/services/attachListener.cpp index 92d3c302ded..976b975602b 100644 --- a/src/hotspot/share/services/attachListener.cpp +++ b/src/hotspot/share/services/attachListener.cpp @@ -387,11 +387,11 @@ static jint jcmd(AttachOperation* op, attachStream* out) { Executor(DCmdSource source, attachStream* out, bool allow_streaming_output) : DCmd::Executor(source, out), _attach_stream(out), _allow_streaming_output(allow_streaming_output) {} protected: - virtual void execute(DCmd* command, TRAPS) override { + void execute(DCmd* command, const JcmdOptions& commonOptions, TRAPS) override { if (_allow_streaming_output) { _attach_stream->set_result(JNI_OK); } - DCmd::Executor::execute(command, CHECK); + DCmd::Executor::execute(command, commonOptions, CHECK); } } executor(DCmd_Source_AttachAPI, out, allow_streaming_output); diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 05c3ab809a8..5dde6164d75 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -188,7 +188,7 @@ static void print_local_time(outputStream* output) { } -void HelpDCmd::execute(DCmdSource source, TRAPS) { +void HelpDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (_all.value()) { GrowableArray* cmd_list = DCmdFactory::DCmd_list(source); cmd_list->sort(compare_strings); @@ -231,7 +231,7 @@ void HelpDCmd::execute(DCmdSource source, TRAPS) { } } -void VersionDCmd::execute(DCmdSource source, TRAPS) { +void VersionDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { output()->print_cr("%s version %s", VM_Version::vm_name(), VM_Version::vm_release()); JDK_Version jdk_version = JDK_Version::current(); @@ -251,8 +251,11 @@ PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_all); } -void PrintVMFlagsDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void PrintVMFlagsDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + if (_all.value()) { JVMFlag::printFlags(output(), true); } else { @@ -269,7 +272,7 @@ SetVMFlagDCmd::SetVMFlagDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_value); } -void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) { +void SetVMFlagDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { const char* val = nullptr; if (_value.value() != nullptr) { val = _value.value(); @@ -283,7 +286,7 @@ void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) { } } -void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) { +void JVMTIDataDumpDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (JvmtiExport::should_post_data_dump()) { JvmtiExport::post_data_dump(); } @@ -300,7 +303,7 @@ JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_option); } -void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) { +void JVMTIAgentLoadDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (_libpath.value() == nullptr) { output()->print_cr("JVMTI.agent_load dcmd needs library path."); @@ -341,7 +344,7 @@ void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) { #endif // INCLUDE_JVMTI #endif // INCLUDE_SERVICES -void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) { +void PrintSystemPropertiesDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { // load VMSupport Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport(); Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK); @@ -391,7 +394,7 @@ VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_date); } -void VMUptimeDCmd::execute(DCmdSource source, TRAPS) { +void VMUptimeDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (_date.value()) { output()->date_stamp(true, "", ": "); } @@ -400,16 +403,19 @@ void VMUptimeDCmd::execute(DCmdSource source, TRAPS) { output()->print_cr(" s"); } -void VMInfoDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void VMInfoDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + VMError::print_vm_info(_output); } -void SystemGCDCmd::execute(DCmdSource source, TRAPS) { +void SystemGCDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { Universe::heap()->collect(GCCause::_dcmd_gc_run); } -void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) { +void RunFinalizationDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { Klass* k = vmClasses::System_klass(); JavaValue result(T_VOID); JavaCalls::call_static(&result, k, @@ -417,14 +423,20 @@ void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) { vmSymbols::void_method_signature(), CHECK); } -void HeapInfoDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void HeapInfoDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + MutexLocker hl(THREAD, Heap_lock); Universe::heap()->print_heap_on(output()); } -void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void FinalizerInfoDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + ResourceMark rm(THREAD); if (!InstanceKlass::is_finalization_enabled()) { @@ -497,8 +509,11 @@ HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_parallel); } -void HeapDumpDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void HeapDumpDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + jlong level = -1; // -1 means no compression. jlong parallel = HeapDumper::default_num_of_dump_threads(); @@ -545,8 +560,11 @@ ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_parallel_thread_num); } -void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void ClassHistogramDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + jlong num = _parallel_thread_num.value(); if (num < 0) { output()->print_cr("Parallel thread number out of range (>=0): " JLONG_FORMAT, num); @@ -571,8 +589,10 @@ ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_extended); } -void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) { +void ThreadDumpDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + // always timestamp print_local_time(output()); + // thread stacks and JNI global handles VM_PrintThreads op1(output(), _locks.value(), _extended.value(), true /* print JNI handle info */); VMThread::execute(&op1); @@ -697,7 +717,7 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _dcmdparser.add_dcmd_option(&_jdp_name); } -void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) { +void JMXStartRemoteDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -770,7 +790,7 @@ JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) // do nothing } -void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) { +void JMXStartLocalDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -787,7 +807,7 @@ void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) { JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK); } -void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) { +void JMXStopRemoteDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -809,8 +829,11 @@ JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) : // do nothing } -void JMXStatusDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void JMXStatusDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -843,25 +866,37 @@ VMDynamicLibrariesDCmd::VMDynamicLibrariesDCmd(outputStream *output, bool heap_a // do nothing } -void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void VMDynamicLibrariesDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + os::print_dll_info(output()); output()->cr(); } -void CompileQueueDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void CompileQueueDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + VM_PrintCompileQueue printCompileQueueOp(output()); VMThread::execute(&printCompileQueueOp); } -void CodeListDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void CodeListDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + CodeCache::print_codelist(output()); } -void CodeCacheDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void CodeCacheDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + CodeCache::print_layout(output()); } @@ -873,7 +908,7 @@ PerfMapDCmd::PerfMapDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_filename); } -void PerfMapDCmd::execute(DCmdSource source, TRAPS) { +void PerfMapDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { CodeCache::write_perf_map(_filename.value(), output()); } #endif // LINUX @@ -887,8 +922,11 @@ CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_granularity); } -void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void CodeHeapAnalyticsDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + jlong granularity = _granularity.value(); if (granularity < 1) { Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(), @@ -909,8 +947,10 @@ EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_max); } -void EventLogDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void EventLogDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } int max = (int)_max.value(); if (max < 0) { output()->print_cr("Invalid max option: \"%d\".", max); @@ -924,8 +964,10 @@ void EventLogDCmd::execute(DCmdSource source, TRAPS) { } } -void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void CompilerDirectivesPrintDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } DirectivesStack::print(output()); } @@ -935,15 +977,15 @@ CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool _dcmdparser.add_dcmd_argument(&_filename); } -void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) { +void CompilerDirectivesAddDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { DirectivesParser::parse_from_file(_filename.value(), output(), true); } -void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) { +void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { DirectivesStack::pop(1); } -void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) { +void CompilerDirectivesClearDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { DirectivesStack::clear(); } @@ -962,8 +1004,10 @@ ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_classname); } -void ClassHierarchyDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void ClassHierarchyDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } VM_PrintClassHierarchy printClassHierarchyOp(output(), _print_interfaces.value(), _print_subclasses.value(), _classname.value()); VMThread::execute(&printClassHierarchyOp); @@ -1000,14 +1044,17 @@ public: } }; -void ClassesDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void ClassesDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + VM_PrintClasses vmop(output(), _verbose.value()); VMThread::execute(&vmop); } #if INCLUDE_CDS -void AOTEndRecordingDCmd::execute(DCmdSource source, TRAPS) { +void AOTEndRecordingDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { if (!CDSConfig::is_dumping_preimage_static_archive()) { output()->print_cr("AOT.end_recording is unsupported when VM flags -XX:AOTMode=record or -XX:AOTCacheOutput= are missing."); return; @@ -1041,8 +1088,11 @@ DumpSharedArchiveDCmd::DumpSharedArchiveDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_filename); } -void DumpSharedArchiveDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void DumpSharedArchiveDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + jboolean is_static; const char* scmd = _suboption.value(); @@ -1105,7 +1155,7 @@ ThreadDumpToFileDCmd::ThreadDumpToFileDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_argument(&_filepath); } -void ThreadDumpToFileDCmd::execute(DCmdSource source, TRAPS) { +void ThreadDumpToFileDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { bool json = (_format.value() != nullptr) && (strcmp(_format.value(), "json") == 0); char* path = _filepath.value(); bool overwrite = _overwrite.value(); @@ -1182,13 +1232,19 @@ static void execute_vthread_command(Symbol* method_name, outputStream* output, T output->print_raw((const char*)addr, ba->length()); } -void VThreadSchedulerDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void VThreadSchedulerDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + execute_vthread_command(vmSymbols::printScheduler_name(), output(), CHECK); } -void VThreadPollersDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void VThreadPollersDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + execute_vthread_command(vmSymbols::printPollers_name(), output(), CHECK); } @@ -1202,8 +1258,11 @@ CompilationMemoryStatisticDCmd::CompilationMemoryStatisticDCmd(outputStream* out _dcmdparser.add_dcmd_option(&_legend); } -void CompilationMemoryStatisticDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void CompilationMemoryStatisticDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + const size_t minsize = _minsize.has_value() ? _minsize.value()._size : 0; CompilationMemoryStatistic::print_jcmd_report(output(), _verbose.value(), _legend.value(), minsize); } @@ -1212,8 +1271,11 @@ void CompilationMemoryStatisticDCmd::execute(DCmdSource source, TRAPS) { SystemMapDCmd::SystemMapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} -void SystemMapDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void SystemMapDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + MemMapPrinter::print_all_mappings(output()); } @@ -1225,8 +1287,11 @@ SystemDumpMapDCmd::SystemDumpMapDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_filename); } -void SystemDumpMapDCmd::execute(DCmdSource source, TRAPS) { - print_local_time(output()); +void SystemDumpMapDCmd::execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { + if (commonOptions.timestamp == JcmdOptions::TimeStamp::Yes) { + print_local_time(output()); + } + const char* name = _filename.value(); if (name == nullptr || name[0] == 0) { output()->print_cr("filename is empty or not specified. No file written"); diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index c41e7bf2e2e..40748918ceb 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -53,7 +53,7 @@ public: "'help all' will show help for all commands."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class VersionDCmd : public DCmd { @@ -64,7 +64,7 @@ public: return "Print JVM version information."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class CommandLineDCmd : public DCmd { @@ -75,7 +75,7 @@ public: return "Print the command line used to start this VM instance."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS) { + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override { Arguments::print_on(_output); } }; @@ -91,7 +91,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; // See also: print_flag in attachListener.cpp @@ -108,7 +108,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class SetVMFlagDCmd : public DCmdWithParser { @@ -126,7 +126,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class JVMTIDataDumpDCmd : public DCmd { @@ -139,7 +139,7 @@ public: static const char* impact() { return "High"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #if INCLUDE_SERVICES @@ -156,7 +156,7 @@ public: return "Load JVMTI native agent."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // INCLUDE_JVMTI #endif // INCLUDE_SERVICES @@ -173,7 +173,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class VMUptimeDCmd : public DCmdWithParser { @@ -189,7 +189,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class VMInfoDCmd : public DCmd { @@ -200,7 +200,7 @@ public: return "Print information about JVM environment and status."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class SystemGCDCmd : public DCmd { @@ -213,7 +213,7 @@ public: static const char* impact() { return "Medium: Depends on Java heap size and content."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class RunFinalizationDCmd : public DCmd { @@ -226,7 +226,7 @@ public: static const char* impact() { return "Medium: Depends on Java content."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class HeapInfoDCmd : public DCmd { @@ -240,7 +240,7 @@ public: return "Medium"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class FinalizerInfoDCmd : public DCmd { @@ -254,7 +254,7 @@ public: return "Medium"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #if INCLUDE_SERVICES // Heap dumping supported @@ -279,7 +279,7 @@ public: return "High: Depends on Java heap size and content. " "Request a full GC unless the '-all' option is specified."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // INCLUDE_SERVICES @@ -300,7 +300,7 @@ public: static const char* impact() { return "High: Depends on Java heap size and content."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class ClassHierarchyDCmd : public DCmdWithParser { @@ -322,7 +322,7 @@ public: static const char* impact() { return "Medium: Depends on number of loaded classes."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #if INCLUDE_CDS @@ -336,7 +336,7 @@ public: static const char* impact() { return "Medium: Pause time depends on number of loaded classes"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // INCLUDE_CDS @@ -357,7 +357,7 @@ public: static const char* impact() { return "Medium: Pause time depends on number of loaded classes"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // INCLUDE_CDS @@ -378,7 +378,7 @@ public: static const char* impact() { return "Medium: Depends on the number of threads."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; // Enhanced JMX Agent support @@ -428,7 +428,7 @@ public: return "Start remote management agent."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class JMXStartLocalDCmd : public DCmd { @@ -448,7 +448,7 @@ public: return "Start local management agent."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; @@ -467,7 +467,7 @@ public: return "Stop remote management agent."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; // Print the JMX system status @@ -483,7 +483,7 @@ public: return "Print the management agent status."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; @@ -499,7 +499,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #ifdef LINUX @@ -518,7 +518,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // LINUX @@ -534,7 +534,7 @@ public: static const char* impact() { return "Medium"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class CodeCacheDCmd : public DCmd { @@ -549,7 +549,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; //---< BEGIN >--- CodeHeap State Analytics. @@ -570,7 +570,7 @@ public: return "Low: Depends on code heap size and content. " "Holds CodeCache_lock during analysis step, usually sub-second duration."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; //---< END >--- CodeHeap State Analytics. @@ -586,7 +586,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class CompilerDirectivesRemoveDCmd : public DCmd { @@ -601,7 +601,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class CompilerDirectivesAddDCmd : public DCmdWithParser { @@ -619,7 +619,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class CompilerDirectivesClearDCmd : public DCmd { @@ -634,7 +634,7 @@ public: static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; /////////////////////////////////////////////////////////////////////// @@ -695,7 +695,7 @@ public: static const char* impact() { return "Medium: Depends on Java content."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class StringtableDCmd : public DCmdWithParser { @@ -713,7 +713,7 @@ public: static const char* impact() { return "Medium: Depends on Java content."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class SystemDictionaryDCmd : public DCmdWithParser { @@ -731,7 +731,7 @@ public: static const char* impact() { return "Medium: Depends on Java content."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class ClassesDCmd : public DCmdWithParser { @@ -749,7 +749,7 @@ public: static const char* impact() { return "Medium: Depends on number of loaded classes."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class EventLogDCmd : public DCmdWithParser { @@ -768,7 +768,7 @@ public: static const char* impact() { return "Low: Depends on event log size. "; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class ThreadDumpToFileDCmd : public DCmdWithParser { @@ -791,7 +791,7 @@ public: static const char* impact() { return "Medium: Depends on the number of threads."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class VThreadSchedulerDCmd : public DCmd { @@ -805,7 +805,7 @@ public: "virtual threads doing timed operations."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class VThreadPollersDCmd : public DCmd { @@ -818,7 +818,7 @@ public: return "Print the I/O pollers that support virtual threads doing blocking network I/O operations."; } static const char* impact() { return "Low"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class CompilationMemoryStatisticDCmd: public DCmdWithParser { @@ -838,7 +838,7 @@ public: static const char* impact() { return "Medium: Pause time depends on number of compiled methods"; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__) @@ -851,7 +851,7 @@ public: return "Prints an annotated process memory map of the VM process (linux, Windows and MacOS only)."; } static const char* impact() { return "Medium; can be high for very large java heaps."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; class SystemDumpMapDCmd : public DCmdWithParser { @@ -864,7 +864,7 @@ public: return "Dumps an annotated process memory map to an output file (linux, Windows and MacOS only)."; } static const char* impact() { return "Medium; can be high for very large java heaps."; } - virtual void execute(DCmdSource source, TRAPS); + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override; }; #endif // LINUX, WINDOWS or MACOS diff --git a/src/hotspot/share/services/diagnosticFramework.cpp b/src/hotspot/share/services/diagnosticFramework.cpp index 71cc461f161..371dd968292 100644 --- a/src/hotspot/share/services/diagnosticFramework.cpp +++ b/src/hotspot/share/services/diagnosticFramework.cpp @@ -379,6 +379,58 @@ GrowableArray* DCmdParser::argument_info_array() const { DCmdFactory* DCmdFactory::_DCmdFactoryList = nullptr; bool DCmdFactory::_has_pending_jmx_notification = false; + +// struct JcmdOptions { +// enum class TimeStamp { +// Default, +// Yes, +// No +// }; + +// TimeStamp timestamp; +// }; + + +// removes globals from the cmdline. +/** + * function to parse common option, preceeding the command. + * @param line - a command line with leading common options "[options] " + * @param updated_line - return value with "" + */ +static JcmdOptions parse_global_options(const CmdLine& line, stringStream *updated_line) { + JcmdOptions options = {}; + + // there is only TIMESTAMP option so far + const char TIMESTAMP[] = "-T"; + + const char* line_str = line.cmd_addr(); + + // TODO: loop until unknown thing. + + stringStream cmd; + cmd.print("%s", line.cmd_addr()); + char* rest = cmd.as_string(); + for (char* token = strtok_r(rest, " ", &rest); + token != nullptr; + token = strtok_r(nullptr, " ", &rest)) { + + // there only one option for now. + if (strcmp(token, TIMESTAMP) == 0) { + options.timestamp = JcmdOptions::TimeStamp::Yes; + + // save the remainder before + line_str = strstr(line_str, rest); + } else { + break; + } + } + + updated_line->write(line_str, strlen(line_str)); + + return options; +} + + void DCmd::Executor::parse_and_execute(const char* cmdline, char delim, TRAPS) { if (cmdline == nullptr) return; // Nothing to do! @@ -393,14 +445,28 @@ void DCmd::Executor::parse_and_execute(const char* cmdline, char delim, TRAPS) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Invalid syntax"); } - CmdLine line = iter.next(); + + // > jcmd [options] [args] + // ^^^^^^^^^^^^^^^^^^^^^^^^^^ + const CmdLine line_optioned = iter.next(); + + // parse options + stringStream ss_line_naked; + const JcmdOptions options = parse_global_options(line_optioned, &ss_line_naked); + + // > jcmd [options] [args] + // ^^^^^^^^^^^^^^^^ + CmdLine line(ss_line_naked.base(), ss_line_naked.size(), false); + if (line.is_stop()) { break; } + if (line.is_executable()) { - // Allow for " -h|-help|--help" to enable the help diagnostic command. - // Ignores any additional arguments. ResourceMark rm; + + // treat trailing {-h,-help,--help} as help command + // Ignores any additional arguments. stringStream updated_line; if (reorder_help_cmd(line, updated_line)) { CmdLine updated_cmd(updated_line.base(), updated_line.size(), false); @@ -411,14 +477,14 @@ void DCmd::Executor::parse_and_execute(const char* cmdline, char delim, TRAPS) { assert(command != nullptr, "command error must be handled before this line"); DCmdMark mark(command); command->parse(&line, delim, CHECK); - execute(command, CHECK); + execute(command, options, CHECK); } count++; } } -void DCmd::Executor::execute(DCmd* command, TRAPS) { - command->execute(_source, CHECK); +void DCmd::Executor::execute(DCmd* command, const JcmdOptions& commonOptions, TRAPS) { + command->execute(_source, commonOptions, CHECK); } void DCmd::parse_and_execute(DCmdSource source, outputStream* out, @@ -426,20 +492,29 @@ void DCmd::parse_and_execute(DCmdSource source, outputStream* out, Executor(source, out).parse_and_execute(cmdline, delim, CHECK); } -bool DCmd::reorder_help_cmd(CmdLine line, stringStream &updated_line) { + +/** + * @desc funtion transorm " [args] {-h,-help,--help}" to a help command "help ..." + * @param line - original line + * @param updated_line - an updated line (return value) + * @return true if @p line contained {-h,-help,--help}, false otherwise. + */ +bool DCmd::reorder_help_cmd(const CmdLine& line, stringStream &updated_line) { stringStream args; args.print("%s", line.args_addr()); - char* rest = args.as_string(); - char* token = strtok_r(rest, " ", &rest); - while (token != nullptr) { - if (strcmp(token, "-h") == 0 || strcmp(token, "--help") == 0 || - strcmp(token, "-help") == 0) { + char* rest = args.as_string(); // as_string() allocates a new string, a copy of `args` + + for (char* token = strtok_r(rest, " ", &rest); + token != nullptr; + token = strtok_r(rest, " ", &rest)) { + if (strcmp(token, "-h") == 0 + || strcmp(token, "--help") == 0 + || strcmp(token, "-help") == 0) { updated_line.print("%s", "help "); updated_line.write(line.cmd_addr(), line.cmd_len()); updated_line.write("\0", 1); return true; } - token = strtok_r(rest, " ", &rest); } return false; diff --git a/src/hotspot/share/services/diagnosticFramework.hpp b/src/hotspot/share/services/diagnosticFramework.hpp index 5f9253b492e..3c920c7373e 100644 --- a/src/hotspot/share/services/diagnosticFramework.hpp +++ b/src/hotspot/share/services/diagnosticFramework.hpp @@ -164,6 +164,17 @@ public: int position() const { return _position; } }; + +struct JcmdOptions { + enum class TimeStamp { + Default, + Yes, + No + }; + + TimeStamp timestamp; +}; + // 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 @@ -258,7 +269,7 @@ public: "The argument list of this diagnostic command should be empty."); } } - virtual void execute(DCmdSource source, TRAPS) { } + virtual void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) { } virtual void reset(TRAPS) { } virtual void cleanup() { } @@ -274,6 +285,7 @@ public: // helper class to invoke the framework class Executor : public StackObj { + DCmdSource _source; outputStream* _out; public: @@ -282,7 +294,7 @@ public: void parse_and_execute(const char* cmdline, char delim, TRAPS); protected: - virtual void execute(DCmd* command, TRAPS); + virtual void execute(DCmd* command, const JcmdOptions& commonOptions, TRAPS); }; // main method to invoke the framework @@ -295,7 +307,7 @@ public: // Helper method to substitute help options " -h|-help|--help" // for "help ". - static bool reorder_help_cmd(CmdLine line, stringStream& updated_line); + static bool reorder_help_cmd(const CmdLine& line, stringStream& updated_line); }; class DCmdWithParser : public DCmd { @@ -306,7 +318,7 @@ public: static const char* disabled_message() { return "Diagnostic command currently disabled"; } static const char* impact() { return "Low: No impact"; } virtual void parse(CmdLine *line, char delim, TRAPS); - virtual void execute(DCmdSource source, TRAPS) { } + void execute(DCmdSource source, const JcmdOptions& commonOptions, TRAPS) override { } virtual void reset(TRAPS); virtual void cleanup(); virtual void print_help(const char* name) const; diff --git a/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java b/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java index 09bde36d0fe..a0e52538a77 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java +++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java @@ -50,19 +50,36 @@ class Arguments { return; } - if (args[0].equals("-?") || - args[0].equals("-h") || - args[0].equals("--help") || - // -help: legacy. - args[0].equals("-help")) { + if (args[0].equals("-?") + || args[0].equals("-h") + || args[0].equals("--help") + || args[0].equals("-help")) { // -help: legacy. showUsage = true; return; } - processString = args[0]; - + int argsCounter = 0; StringBuilder sb = new StringBuilder(); - for (int i = 1; i < args.length; i++) { + + // {,
} + processString = args[argsCounter]; + argsCounter++; + + // common flags: [-T] + if (argsCounter < args.length // "jcmd " is valid and acts like "jcmd help" + && args[argsCounter].equals("-T")) { + sb.append(args[argsCounter]).append(" "); + argsCounter++; + + // common flag should be followed by commands + if (args.length == argsCounter + 1) { + throw new IllegalArgumentException( + "Not enough arguments.\n" + + "Usage: jcmd [-T] "); + } + } + + for (int i = argsCounter; i < args.length; i++) { if (args[i].equals("-f")) { if (args.length == i + 1) { throw new IllegalArgumentException( @@ -108,11 +125,13 @@ class Arguments { } public static void usage() { - System.out.println("Usage: jcmd "); + System.out.println("Usage: jcmd [-T] "); System.out.println(" or: jcmd -l "); System.out.println(" or: jcmd -h "); System.out.println(" "); - System.out.println(" command must be a valid jcmd command for the selected jvm. "); + System.out.println(" -T flag ensures the dignostic command begins with a timestamp "); + System.out.println(" "); + System.out.println(" command must be a valid jcmd command for the selected JVM. "); System.out.println(" Use the command \"help\" to see which commands are available. "); System.out.println(" If the pid is 0, commands will be sent to all Java processes. "); System.out.println(" The main class argument will be used to match (either partially ");