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