1 /*
  2  * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_SERVICES_DIAGNOSTICCOMMAND_HPP
 26 #define SHARE_SERVICES_DIAGNOSTICCOMMAND_HPP
 27 
 28 #include "classfile/stringTable.hpp"
 29 #include "classfile/symbolTable.hpp"
 30 #include "classfile/systemDictionary.hpp"
 31 #include "classfile/vmSymbols.hpp"
 32 #include "oops/method.hpp"
 33 #include "runtime/arguments.hpp"
 34 #include "runtime/os.hpp"
 35 #include "runtime/vmThread.hpp"
 36 #include "services/diagnosticArgument.hpp"
 37 #include "services/diagnosticCommand.hpp"
 38 #include "services/diagnosticFramework.hpp"
 39 #include "utilities/macros.hpp"
 40 #include "utilities/ostream.hpp"
 41 
 42 class HelpDCmd : public DCmdWithParser {
 43 protected:
 44   DCmdArgument<bool> _all;
 45   DCmdArgument<char*> _cmd;
 46 public:
 47   static int num_arguments() { return 2; }
 48   HelpDCmd(outputStream* output, bool heap);
 49   static const char* name() { return "help"; }
 50   static const char* description() {
 51     return "For more information about a specific command use 'help <command>'. "
 52            "With no argument this will show a list of available commands. "
 53            "'help all' will show help for all commands.";
 54   }
 55   static const char* impact() { return "Low"; }
 56   virtual void execute(DCmdSource source, TRAPS);
 57 };
 58 
 59 class VersionDCmd : public DCmd {
 60 public:
 61   VersionDCmd(outputStream* output, bool heap) : DCmd(output,heap) { }
 62   static const char* name() { return "VM.version"; }
 63   static const char* description() {
 64     return "Print JVM version information.";
 65   }
 66   static const char* impact() { return "Low"; }
 67   virtual void execute(DCmdSource source, TRAPS);
 68 };
 69 
 70 class CommandLineDCmd : public DCmd {
 71 public:
 72   CommandLineDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 73   static const char* name() { return "VM.command_line"; }
 74   static const char* description() {
 75     return "Print the command line used to start this VM instance.";
 76   }
 77   static const char* impact() { return "Low"; }
 78   virtual void execute(DCmdSource source, TRAPS) {
 79     Arguments::print_on(_output);
 80   }
 81 };
 82 
 83 // See also: get_system_properties in attachListener.cpp
 84 class PrintSystemPropertiesDCmd : public DCmd {
 85 public:
 86   PrintSystemPropertiesDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 87     static const char* name() { return "VM.system_properties"; }
 88     static const char* description() {
 89       return "Print system properties.";
 90     }
 91     static const char* impact() {
 92       return "Low";
 93     }
 94     virtual void execute(DCmdSource source, TRAPS);
 95 };
 96 
 97 // See also: print_flag in attachListener.cpp
 98 class PrintVMFlagsDCmd : public DCmdWithParser {
 99 protected:
100   DCmdArgument<bool> _all;
101 public:
102   static int num_arguments() { return 1; }
103   PrintVMFlagsDCmd(outputStream* output, bool heap);
104   static const char* name() { return "VM.flags"; }
105   static const char* description() {
106     return "Print VM flag options and their current values.";
107   }
108   static const char* impact() {
109     return "Low";
110   }
111   virtual void execute(DCmdSource source, TRAPS);
112 };
113 
114 class SetVMFlagDCmd : public DCmdWithParser {
115 protected:
116   DCmdArgument<char*> _flag;
117   DCmdArgument<char*> _value;
118 
119 public:
120   static int num_arguments() { return 2; }
121   SetVMFlagDCmd(outputStream* output, bool heap);
122   static const char* name() { return "VM.set_flag"; }
123   static const char* description() {
124     return "Sets VM flag option using the provided value.";
125   }
126   static const char* impact() {
127     return "Low";
128   }
129   virtual void execute(DCmdSource source, TRAPS);
130 };
131 
132 class JVMTIDataDumpDCmd : public DCmd {
133 public:
134   JVMTIDataDumpDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
135   static const char* name() { return "JVMTI.data_dump"; }
136   static const char* description() {
137     return "Signal the JVM to do a data-dump request for JVMTI.";
138   }
139   static const char* impact() {
140     return "High";
141   }
142   virtual void execute(DCmdSource source, TRAPS);
143 };
144 
145 #if INCLUDE_SERVICES
146 #if INCLUDE_JVMTI
147 class JVMTIAgentLoadDCmd : public DCmdWithParser {
148 protected:
149   DCmdArgument<char*> _libpath;
150   DCmdArgument<char*> _option;
151 public:
152   static int num_arguments() { return 2; }
153   JVMTIAgentLoadDCmd(outputStream* output, bool heap);
154   static const char* name() { return "JVMTI.agent_load"; }
155   static const char* description() {
156     return "Load JVMTI native agent.";
157   }
158   static const char* impact() { return "Low"; }
159   virtual void execute(DCmdSource source, TRAPS);
160 };
161 #endif // INCLUDE_JVMTI
162 #endif // INCLUDE_SERVICES
163 
164 class VMDynamicLibrariesDCmd : public DCmd {
165 public:
166   VMDynamicLibrariesDCmd(outputStream* output, bool heap);
167   static const char* name() {
168     return "VM.dynlibs";
169   }
170   static const char* description() {
171     return "Print loaded dynamic libraries.";
172   }
173   static const char* impact() {
174     return "Low";
175   }
176   virtual void execute(DCmdSource source, TRAPS);
177 };
178 
179 class VMUptimeDCmd : public DCmdWithParser {
180 protected:
181   DCmdArgument<bool> _date;
182 public:
183   static int num_arguments() { return 1; }
184   VMUptimeDCmd(outputStream* output, bool heap);
185   static const char* name() { return "VM.uptime"; }
186   static const char* description() {
187     return "Print VM uptime.";
188   }
189   static const char* impact() {
190     return "Low";
191   }
192   virtual void execute(DCmdSource source, TRAPS);
193 };
194 
195 class VMInfoDCmd : public DCmd {
196 public:
197   VMInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
198   static const char* name() { return "VM.info"; }
199   static const char* description() {
200     return "Print information about JVM environment and status.";
201   }
202   static const char* impact() { return "Low"; }
203   virtual void execute(DCmdSource source, TRAPS);
204 };
205 
206 class SystemGCDCmd : public DCmd {
207 public:
208   SystemGCDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
209     static const char* name() { return "GC.run"; }
210     static const char* description() {
211       return "Call java.lang.System.gc().";
212     }
213     static const char* impact() {
214       return "Medium: Depends on Java heap size and content.";
215     }
216     virtual void execute(DCmdSource source, TRAPS);
217 };
218 
219 class RunFinalizationDCmd : public DCmd {
220 public:
221   RunFinalizationDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
222     static const char* name() { return "GC.run_finalization"; }
223     static const char* description() {
224       return "Call java.lang.System.runFinalization().";
225     }
226     static const char* impact() {
227       return "Medium: Depends on Java content.";
228     }
229     virtual void execute(DCmdSource source, TRAPS);
230 };
231 
232 class HeapInfoDCmd : public DCmd {
233 public:
234   HeapInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
235   static const char* name() { return "GC.heap_info"; }
236   static const char* description() {
237     return "Provide generic Java heap information.";
238   }
239   static const char* impact() {
240     return "Medium";
241   }
242 
243   virtual void execute(DCmdSource source, TRAPS);
244 };
245 
246 class FinalizerInfoDCmd : public DCmd {
247 public:
248   FinalizerInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
249   static const char* name() { return "GC.finalizer_info"; }
250   static const char* description() {
251     return "Provide information about Java finalization queue.";
252   }
253   static const char* impact() {
254     return "Medium";
255   }
256 
257   virtual void execute(DCmdSource source, TRAPS);
258 };
259 
260 #if INCLUDE_SERVICES   // Heap dumping supported
261 // See also: dump_heap in attachListener.cpp
262 class HeapDumpDCmd : public DCmdWithParser {
263 protected:
264   DCmdArgument<char*> _filename;
265   DCmdArgument<bool>  _all;
266   DCmdArgument<jlong> _gzip;
267   DCmdArgument<bool> _overwrite;
268   DCmdArgument<jlong> _parallel;
269 public:
270   static int num_arguments() { return 5; }
271   HeapDumpDCmd(outputStream* output, bool heap);
272   static const char* name() {
273     return "GC.heap_dump";
274   }
275   static const char* description() {
276     return "Generate a HPROF format dump of the Java heap.";
277   }
278   static const char* impact() {
279     return "High: Depends on Java heap size and content. "
280            "Request a full GC unless the '-all' option is specified.";
281   }
282   virtual void execute(DCmdSource source, TRAPS);
283 };
284 #endif // INCLUDE_SERVICES
285 
286 // See also: inspectheap in attachListener.cpp
287 class ClassHistogramDCmd : public DCmdWithParser {
288 protected:
289   DCmdArgument<bool> _all;
290   DCmdArgument<jlong> _parallel_thread_num;
291 public:
292   static int num_arguments() { return 2; }
293   ClassHistogramDCmd(outputStream* output, bool heap);
294   static const char* name() {
295     return "GC.class_histogram";
296   }
297   static const char* description() {
298     return "Provide statistics about the Java heap usage.";
299   }
300   static const char* impact() {
301     return "High: Depends on Java heap size and content.";
302   }
303   virtual void execute(DCmdSource source, TRAPS);
304 };
305 
306 class ClassHierarchyDCmd : public DCmdWithParser {
307 protected:
308   DCmdArgument<bool> _print_interfaces; // true if inherited interfaces should be printed.
309   DCmdArgument<bool> _print_subclasses; // true if subclasses of the specified classname should be printed.
310   DCmdArgument<char*> _classname; // Optional single class name whose hierarchy should be printed.
311 public:
312   static int num_arguments() { return 3; }
313   ClassHierarchyDCmd(outputStream* output, bool heap);
314   static const char* name() {
315     return "VM.class_hierarchy";
316   }
317   static const char* description() {
318     return "Print a list of all loaded classes, indented to show the class hierarchy. "
319            "The name of each class is followed by the ClassLoaderData* of its ClassLoader, "
320            "or \"null\" if loaded by the bootstrap class loader.";
321   }
322   static const char* impact() {
323       return "Medium: Depends on number of loaded classes.";
324   }
325   virtual void execute(DCmdSource source, TRAPS);
326 };
327 
328 class PrintClassLayoutDCmd : public DCmdWithParser {
329 protected:
330   DCmdArgument<char*> _classname; // lass name whose layout should be printed.
331 public:
332   PrintClassLayoutDCmd(outputStream* output, bool heap);
333   static const char* name() {
334     return "VM.class_print_layout";
335   }
336   static const char* description() {
337     return "Print the layout of an instance of a class, including flat fields. "
338            "The name of each class is followed by the ClassLoaderData* of its ClassLoader, "
339            "or \"null\" if loaded by the bootstrap class loader.";
340   }
341   static const char* impact() {
342       return "Medium: Depends on number of loaded classes.";
343   }
344   static int num_arguments();
345   virtual void execute(DCmdSource source, TRAPS);
346 };
347 
348 #if INCLUDE_CDS
349 class AOTEndRecordingDCmd : public DCmd {
350 public:
351   AOTEndRecordingDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
352     static const char* name() { return "AOT.end_recording"; }
353     static const char* description() {
354       return "End AOT recording.";
355     }
356     static const char* impact() {
357       return "Medium: Pause time depends on number of loaded classes";
358     }
359     virtual void execute(DCmdSource source, TRAPS);
360 };
361 #endif // INCLUDE_CDS
362 
363 #if INCLUDE_CDS
364 class DumpSharedArchiveDCmd: public DCmdWithParser {
365 protected:
366   DCmdArgument<char*> _suboption;   // option of VM.cds
367   DCmdArgument<char*> _filename;    // file name, optional
368 public:
369   static int num_arguments() { return 2; }
370   DumpSharedArchiveDCmd(outputStream* output, bool heap);
371   static const char* name() {
372     return "VM.cds";
373   }
374   static const char* description() {
375     return "Dump a static or dynamic shared archive including all shareable classes";
376   }
377   static const char* impact() {
378     return "Medium: Pause time depends on number of loaded classes";
379   }
380   virtual void execute(DCmdSource source, TRAPS);
381 };
382 #endif // INCLUDE_CDS
383 
384 // See also: thread_dump in attachListener.cpp
385 class ThreadDumpDCmd : public DCmdWithParser {
386 protected:
387   DCmdArgument<bool> _locks;
388   DCmdArgument<bool> _extended;
389 public:
390   static int num_arguments() { return 2; }
391   ThreadDumpDCmd(outputStream* output, bool heap);
392   static const char* name() { return "Thread.print"; }
393   static const char* description() {
394     return "Print all platform threads, and mounted virtual threads, "
395            "with stack traces. The Thread.dump_to_file command will "
396            "print all threads to a file.";
397   }
398   static const char* impact() {
399     return "Medium: Depends on the number of threads.";
400   }
401   virtual void execute(DCmdSource source, TRAPS);
402 };
403 
404 // Enhanced JMX Agent support
405 
406 class JMXStartRemoteDCmd : public DCmdWithParser {
407 
408   // Explicitly list all properties that could be
409   // passed to Agent.startRemoteManagementAgent()
410   // com.sun.management is omitted
411 
412   DCmdArgument<char *> _config_file;
413   DCmdArgument<char *> _jmxremote_host;
414   DCmdArgument<char *> _jmxremote_port;
415   DCmdArgument<char *> _jmxremote_rmi_port;
416   DCmdArgument<char *> _jmxremote_ssl;
417   DCmdArgument<char *> _jmxremote_registry_ssl;
418   DCmdArgument<char *> _jmxremote_authenticate;
419   DCmdArgument<char *> _jmxremote_password_file;
420   DCmdArgument<char *> _jmxremote_access_file;
421   DCmdArgument<char *> _jmxremote_login_config;
422   DCmdArgument<char *> _jmxremote_ssl_enabled_cipher_suites;
423   DCmdArgument<char *> _jmxremote_ssl_enabled_protocols;
424   DCmdArgument<char *> _jmxremote_ssl_need_client_auth;
425   DCmdArgument<char *> _jmxremote_ssl_config_file;
426 
427   // JDP support
428   // Keep autodiscovery char* not bool to pass true/false
429   // as property value to java level.
430   DCmdArgument<char *> _jmxremote_autodiscovery;
431   DCmdArgument<jlong>  _jdp_port;
432   DCmdArgument<char *> _jdp_address;
433   DCmdArgument<char *> _jdp_source_addr;
434   DCmdArgument<jlong>  _jdp_ttl;
435   DCmdArgument<jlong>  _jdp_pause;
436   DCmdArgument<char *> _jdp_name;
437 
438 public:
439   static int num_arguments() { return 21; }
440 
441   JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
442 
443   static const char *name() {
444     return "ManagementAgent.start";
445   }
446 
447   static const char *description() {
448     return "Start remote management agent.";
449   }
450 
451   virtual void execute(DCmdSource source, TRAPS);
452 };
453 
454 class JMXStartLocalDCmd : public DCmd {
455 
456   // Explicitly request start of local agent,
457   // it will not be started by start dcmd
458 
459 
460 public:
461   JMXStartLocalDCmd(outputStream *output, bool heap_allocated);
462 
463   static const char *name() {
464     return "ManagementAgent.start_local";
465   }
466 
467   static const char *description() {
468     return "Start local management agent.";
469   }
470 
471   virtual void execute(DCmdSource source, TRAPS);
472 
473 };
474 
475 class JMXStopRemoteDCmd : public DCmd {
476 public:
477   JMXStopRemoteDCmd(outputStream *output, bool heap_allocated) :
478   DCmd(output, heap_allocated) {
479     // Do Nothing
480   }
481 
482   static const char *name() {
483     return "ManagementAgent.stop";
484   }
485 
486   static const char *description() {
487     return "Stop remote management agent.";
488   }
489 
490   virtual void execute(DCmdSource source, TRAPS);
491 };
492 
493 // Print the JMX system status
494 class JMXStatusDCmd : public DCmd {
495 public:
496   JMXStatusDCmd(outputStream *output, bool heap_allocated);
497 
498   static const char *name() {
499     return "ManagementAgent.status";
500   }
501 
502   static const char *description() {
503     return "Print the management agent status.";
504   }
505 
506   virtual void execute(DCmdSource source, TRAPS);
507 
508 };
509 
510 class CompileQueueDCmd : public DCmd {
511 public:
512   CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
513   static const char* name() {
514     return "Compiler.queue";
515   }
516   static const char* description() {
517     return "Print methods queued for compilation.";
518   }
519   static const char* impact() {
520     return "Low";
521   }
522   virtual void execute(DCmdSource source, TRAPS);
523 };
524 
525 #ifdef LINUX
526 class PerfMapDCmd : public DCmdWithParser {
527 protected:
528   DCmdArgument<char*> _filename;
529 public:
530   static int num_arguments() { return 1; }
531   PerfMapDCmd(outputStream* output, bool heap);
532   static const char* name() {
533     return "Compiler.perfmap";
534   }
535   static const char* description() {
536     return "Write map file for Linux perf tool.";
537   }
538   static const char* impact() {
539     return "Low";
540   }
541   virtual void execute(DCmdSource source, TRAPS);
542 };
543 #endif // LINUX
544 
545 class CodeListDCmd : public DCmd {
546 public:
547   CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
548   static const char* name() {
549     return "Compiler.codelist";
550   }
551   static const char* description() {
552     return "Print all compiled methods in code cache that are alive";
553   }
554   static const char* impact() {
555     return "Medium";
556   }
557   virtual void execute(DCmdSource source, TRAPS);
558 };
559 
560 class CodeCacheDCmd : public DCmd {
561 public:
562   CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
563   static const char* name() {
564     return "Compiler.codecache";
565   }
566   static const char* description() {
567     return "Print code cache layout and bounds.";
568   }
569   static const char* impact() {
570     return "Low";
571   }
572   virtual void execute(DCmdSource source, TRAPS);
573 };
574 
575 //---<  BEGIN  >--- CodeHeap State Analytics.
576 class CodeHeapAnalyticsDCmd : public DCmdWithParser {
577 protected:
578   DCmdArgument<char*> _function;
579   DCmdArgument<jlong> _granularity;
580 public:
581   static int num_arguments() { return 2; }
582   CodeHeapAnalyticsDCmd(outputStream* output, bool heap);
583   static const char* name() {
584     return "Compiler.CodeHeap_Analytics";
585   }
586   static const char* description() {
587     return "Print CodeHeap analytics";
588   }
589   static const char* impact() {
590     return "Low: Depends on code heap size and content. "
591            "Holds CodeCache_lock during analysis step, usually sub-second duration.";
592   }
593   virtual void execute(DCmdSource source, TRAPS);
594 };
595 //---<  END  >--- CodeHeap State Analytics.
596 
597 class CompilerDirectivesPrintDCmd : public DCmd {
598 public:
599   CompilerDirectivesPrintDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
600   static const char* name() {
601     return "Compiler.directives_print";
602   }
603   static const char* description() {
604     return "Print all active compiler directives.";
605   }
606   static const char* impact() {
607     return "Low";
608   }
609   virtual void execute(DCmdSource source, TRAPS);
610 };
611 
612 class CompilerDirectivesRemoveDCmd : public DCmd {
613 public:
614   CompilerDirectivesRemoveDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
615   static const char* name() {
616     return "Compiler.directives_remove";
617   }
618   static const char* description() {
619     return "Remove latest added compiler directive.";
620   }
621   static const char* impact() {
622     return "Low";
623   }
624   virtual void execute(DCmdSource source, TRAPS);
625 };
626 
627 class CompilerDirectivesAddDCmd : public DCmdWithParser {
628 protected:
629   DCmdArgument<char*> _filename;
630 public:
631   static int num_arguments() { return 1; }
632   CompilerDirectivesAddDCmd(outputStream* output, bool heap);
633   static const char* name() {
634     return "Compiler.directives_add";
635   }
636   static const char* description() {
637     return "Add compiler directives from file.";
638   }
639   static const char* impact() {
640     return "Low";
641   }
642   virtual void execute(DCmdSource source, TRAPS);
643 };
644 
645 class CompilerDirectivesClearDCmd : public DCmd {
646 public:
647   CompilerDirectivesClearDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
648   static const char* name() {
649     return "Compiler.directives_clear";
650   }
651   static const char* description() {
652     return "Remove all compiler directives.";
653   }
654   static const char* impact() {
655     return "Low";
656   }
657   virtual void execute(DCmdSource source, TRAPS);
658 };
659 
660 ///////////////////////////////////////////////////////////////////////
661 //
662 // jcmd command support for symbol table, string table and system dictionary dumping:
663 //   VM.symboltable -verbose: for dumping the symbol table
664 //   VM.stringtable -verbose: for dumping the string table
665 //   VM.systemdictionary -verbose: for dumping the system dictionary table
666 //
667 class VM_DumpHashtable : public VM_Operation {
668 private:
669   outputStream* _out;
670   int _which;
671   bool _verbose;
672 public:
673   enum {
674     DumpSymbols = 1 << 0,
675     DumpStrings = 1 << 1,
676     DumpSysDict = 1 << 2  // not implemented yet
677   };
678   VM_DumpHashtable(outputStream* out, int which, bool verbose) {
679     _out = out;
680     _which = which;
681     _verbose = verbose;
682   }
683 
684   virtual VMOp_Type type() const { return VMOp_DumpHashtable; }
685 
686   virtual void doit() {
687     switch (_which) {
688     case DumpSymbols:
689       SymbolTable::dump(_out, _verbose);
690       break;
691     case DumpStrings:
692       StringTable::dump(_out, _verbose);
693       break;
694     case DumpSysDict:
695       SystemDictionary::dump(_out, _verbose);
696       break;
697     default:
698       ShouldNotReachHere();
699     }
700   }
701 };
702 
703 class SymboltableDCmd : public DCmdWithParser {
704 protected:
705   DCmdArgument<bool> _verbose;
706 public:
707   static int num_arguments() { return 1; }
708   SymboltableDCmd(outputStream* output, bool heap);
709   static const char* name() {
710     return "VM.symboltable";
711   }
712   static const char* description() {
713     return "Dump symbol table.";
714   }
715   static const char* impact() {
716     return "Medium: Depends on Java content.";
717   }
718   virtual void execute(DCmdSource source, TRAPS);
719 };
720 
721 class StringtableDCmd : public DCmdWithParser {
722 protected:
723   DCmdArgument<bool> _verbose;
724 public:
725   static int num_arguments() { return 1; }
726   StringtableDCmd(outputStream* output, bool heap);
727   static const char* name() {
728     return "VM.stringtable";
729   }
730   static const char* description() {
731     return "Dump string table.";
732   }
733   static const char* impact() {
734     return "Medium: Depends on Java content.";
735   }
736   virtual void execute(DCmdSource source, TRAPS);
737 };
738 
739 class SystemDictionaryDCmd : public DCmdWithParser {
740 protected:
741   DCmdArgument<bool> _verbose;
742 public:
743   static int num_arguments() { return 1; }
744   SystemDictionaryDCmd(outputStream* output, bool heap);
745   static const char* name() {
746     return "VM.systemdictionary";
747   }
748   static const char* description() {
749     return "Prints the statistics for dictionary hashtable sizes and bucket length";
750   }
751   static const char* impact() {
752       return "Medium: Depends on Java content.";
753   }
754   virtual void execute(DCmdSource source, TRAPS);
755 };
756 
757 class ClassesDCmd : public DCmdWithParser {
758 protected:
759   DCmdArgument<bool> _verbose;
760 public:
761   static int num_arguments() { return 1; }
762   ClassesDCmd(outputStream* output, bool heap);
763   static const char* name() {
764     return "VM.classes";
765   }
766   static const char* description() {
767     return "Print all loaded classes";
768   }
769   static const char* impact() {
770       return "Medium: Depends on number of loaded classes.";
771   }
772   virtual void execute(DCmdSource source, TRAPS);
773 };
774 
775 class EventLogDCmd : public DCmdWithParser {
776 protected:
777   DCmdArgument<char*> _log;
778   DCmdArgument<jlong> _max;
779 public:
780   static int num_arguments() { return 2; }
781   EventLogDCmd(outputStream* output, bool heap);
782   static const char* name() {
783     return "VM.events";
784   }
785   static const char* description() {
786     return "Print VM event logs";
787   }
788   static const char* impact() {
789     return "Low: Depends on event log size. ";
790   }
791   virtual void execute(DCmdSource source, TRAPS);
792 };
793 
794 class ThreadDumpToFileDCmd : public DCmdWithParser {
795 private:
796   void dumpToFile(Symbol* name, Symbol* signature, const char* path, bool overwrite, TRAPS);
797 protected:
798   DCmdArgument<bool> _overwrite;
799   DCmdArgument<char*> _format;
800   DCmdArgument<char*> _filepath;
801 public:
802   static int num_arguments() { return 3; }
803   ThreadDumpToFileDCmd(outputStream *output, bool heap);
804   static const char *name() {
805     return "Thread.dump_to_file";
806   }
807   static const char *description() {
808     return "Dump all threads, with stack traces, "
809            "to a file in plain text or JSON format.";
810   }
811   static const char* impact() {
812     return "Medium: Depends on the number of threads.";
813   }
814   virtual void execute(DCmdSource source, TRAPS);
815 };
816 
817 class VThreadSchedulerDCmd : public DCmd {
818 public:
819   VThreadSchedulerDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
820   static const char* name() {
821     return "Thread.vthread_scheduler";
822   }
823   static const char* description() {
824     return "Print the virtual thread scheduler, and the delayed task schedulers that support "
825            "virtual threads doing timed operations.";
826   }
827   static const char* impact() { return "Low"; }
828   virtual void execute(DCmdSource source, TRAPS);
829 };
830 
831 class VThreadPollersDCmd : public DCmd {
832 public:
833   VThreadPollersDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
834   static const char* name() {
835     return "Thread.vthread_pollers";
836   }
837   static const char* description() {
838     return "Print the I/O pollers that support virtual threads doing blocking network I/O operations.";
839   }
840   static const char* impact() { return "Low"; }
841   virtual void execute(DCmdSource source, TRAPS);
842 };
843 
844 class CompilationMemoryStatisticDCmd: public DCmdWithParser {
845 protected:
846   DCmdArgument<bool> _verbose;
847   DCmdArgument<bool> _legend;
848   DCmdArgument<MemorySizeArgument> _minsize;
849 public:
850   static int num_arguments() { return 3; }
851   CompilationMemoryStatisticDCmd(outputStream* output, bool heap);
852   static const char* name() {
853     return "Compiler.memory";
854   }
855   static const char* description() {
856     return "Print compilation footprint";
857   }
858   static const char* impact() {
859     return "Medium: Pause time depends on number of compiled methods";
860   }
861   virtual void execute(DCmdSource source, TRAPS);
862 };
863 
864 #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__)
865 
866 class SystemMapDCmd : public DCmd {
867 public:
868   SystemMapDCmd(outputStream* output, bool heap);
869   static const char* name() { return "System.map"; }
870   static const char* description() {
871     return "Prints an annotated process memory map of the VM process (linux, Windows and MacOS only).";
872   }
873   static const char* impact() { return "Medium; can be high for very large java heaps."; }
874   virtual void execute(DCmdSource source, TRAPS);
875 };
876 
877 class SystemDumpMapDCmd : public DCmdWithParser {
878   DCmdArgument<char*> _filename;
879 public:
880   static int num_arguments() { return 1; }
881   SystemDumpMapDCmd(outputStream* output, bool heap);
882   static const char* name() { return "System.dump_map"; }
883   static const char* description() {
884     return "Dumps an annotated process memory map to an output file (linux, Windows and MacOS only).";
885   }
886   static const char* impact() { return "Medium; can be high for very large java heaps."; }
887   virtual void execute(DCmdSource source, TRAPS);
888 };
889 
890 #endif // LINUX, WINDOWS or MACOS
891 
892 #endif // SHARE_SERVICES_DIAGNOSTICCOMMAND_HPP