1 /*
   2  * Copyright (c) 2011, 2023, 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 "runtime/arguments.hpp"
  33 #include "runtime/os.hpp"
  34 #include "runtime/vmThread.hpp"
  35 #include "services/diagnosticArgument.hpp"
  36 #include "services/diagnosticCommand.hpp"
  37 #include "services/diagnosticFramework.hpp"
  38 #include "utilities/macros.hpp"
  39 #include "utilities/ostream.hpp"
  40 #include "oops/method.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   static const JavaPermission permission() {
  68     JavaPermission p = {"java.util.PropertyPermission",
  69                         "java.vm.version", "read"};
  70     return p;
  71   }
  72   virtual void execute(DCmdSource source, TRAPS);
  73 };
  74 
  75 class CommandLineDCmd : public DCmd {
  76 public:
  77   CommandLineDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
  78   static const char* name() { return "VM.command_line"; }
  79   static const char* description() {
  80     return "Print the command line used to start this VM instance.";
  81   }
  82   static const char* impact() { return "Low"; }
  83   static const JavaPermission permission() {
  84     JavaPermission p = {"java.lang.management.ManagementPermission",
  85                         "monitor", nullptr};
  86     return p;
  87   }
  88   virtual void execute(DCmdSource source, TRAPS) {
  89     Arguments::print_on(_output);
  90   }
  91 };
  92 
  93 // See also: get_system_properties in attachListener.cpp
  94 class PrintSystemPropertiesDCmd : public DCmd {
  95 public:
  96   PrintSystemPropertiesDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
  97     static const char* name() { return "VM.system_properties"; }
  98     static const char* description() {
  99       return "Print system properties.";
 100     }
 101     static const char* impact() {
 102       return "Low";
 103     }
 104     static const JavaPermission permission() {
 105       JavaPermission p = {"java.util.PropertyPermission",
 106                           "*", "read"};
 107       return p;
 108     }
 109     virtual void execute(DCmdSource source, TRAPS);
 110 };
 111 
 112 // See also: print_flag in attachListener.cpp
 113 class PrintVMFlagsDCmd : public DCmdWithParser {
 114 protected:
 115   DCmdArgument<bool> _all;
 116 public:
 117   static int num_arguments() { return 1; }
 118   PrintVMFlagsDCmd(outputStream* output, bool heap);
 119   static const char* name() { return "VM.flags"; }
 120   static const char* description() {
 121     return "Print VM flag options and their current values.";
 122   }
 123   static const char* impact() {
 124     return "Low";
 125   }
 126   static const JavaPermission permission() {
 127     JavaPermission p = {"java.lang.management.ManagementPermission",
 128                         "monitor", nullptr};
 129     return p;
 130   }
 131   virtual void execute(DCmdSource source, TRAPS);
 132 };
 133 
 134 class SetVMFlagDCmd : public DCmdWithParser {
 135 protected:
 136   DCmdArgument<char*> _flag;
 137   DCmdArgument<char*> _value;
 138 
 139 public:
 140   static int num_arguments() { return 2; }
 141   SetVMFlagDCmd(outputStream* output, bool heap);
 142   static const char* name() { return "VM.set_flag"; }
 143   static const char* description() {
 144     return "Sets VM flag option using the provided value.";
 145   }
 146   static const char* impact() {
 147     return "Low";
 148   }
 149   static const JavaPermission permission() {
 150     JavaPermission p = {"java.lang.management.ManagementPermission",
 151                         "control", nullptr};
 152     return p;
 153   }
 154   virtual void execute(DCmdSource source, TRAPS);
 155 };
 156 
 157 class JVMTIDataDumpDCmd : public DCmd {
 158 public:
 159   JVMTIDataDumpDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 160   static const char* name() { return "JVMTI.data_dump"; }
 161   static const char* description() {
 162     return "Signal the JVM to do a data-dump request for JVMTI.";
 163   }
 164   static const char* impact() {
 165     return "High";
 166   }
 167   static const JavaPermission permission() {
 168     JavaPermission p = {"java.lang.management.ManagementPermission",
 169                         "monitor", nullptr};
 170     return p;
 171   }
 172   virtual void execute(DCmdSource source, TRAPS);
 173 };
 174 
 175 #if INCLUDE_SERVICES
 176 #if INCLUDE_JVMTI
 177 class JVMTIAgentLoadDCmd : public DCmdWithParser {
 178 protected:
 179   DCmdArgument<char*> _libpath;
 180   DCmdArgument<char*> _option;
 181 public:
 182   static int num_arguments() { return 2; }
 183   JVMTIAgentLoadDCmd(outputStream* output, bool heap);
 184   static const char* name() { return "JVMTI.agent_load"; }
 185   static const char* description() {
 186     return "Load JVMTI native agent.";
 187   }
 188   static const char* impact() { return "Low"; }
 189   static const JavaPermission permission() {
 190     JavaPermission p = {"java.lang.management.ManagementPermission",
 191                         "control", nullptr};
 192     return p;
 193   }
 194   virtual void execute(DCmdSource source, TRAPS);
 195 };
 196 #endif // INCLUDE_JVMTI
 197 #endif // INCLUDE_SERVICES
 198 
 199 class VMDynamicLibrariesDCmd : public DCmd {
 200 public:
 201   VMDynamicLibrariesDCmd(outputStream* output, bool heap);
 202   static const char* name() {
 203     return "VM.dynlibs";
 204   }
 205   static const char* description() {
 206     return "Print loaded dynamic libraries.";
 207   }
 208   static const char* impact() {
 209     return "Low";
 210   }
 211   static const JavaPermission permission() {
 212     JavaPermission p = {"java.lang.management.ManagementPermission",
 213                         "monitor", nullptr};
 214     return p;
 215   }
 216   virtual void execute(DCmdSource source, TRAPS);
 217 };
 218 
 219 class VMUptimeDCmd : public DCmdWithParser {
 220 protected:
 221   DCmdArgument<bool> _date;
 222 public:
 223   static int num_arguments() { return 1; }
 224   VMUptimeDCmd(outputStream* output, bool heap);
 225   static const char* name() { return "VM.uptime"; }
 226   static const char* description() {
 227     return "Print VM uptime.";
 228   }
 229   static const char* impact() {
 230     return "Low";
 231   }
 232   virtual void execute(DCmdSource source, TRAPS);
 233 };
 234 
 235 class VMInfoDCmd : public DCmd {
 236 public:
 237   VMInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 238   static const char* name() { return "VM.info"; }
 239   static const char* description() {
 240     return "Print information about JVM environment and status.";
 241   }
 242   static const char* impact() { return "Low"; }
 243   static const JavaPermission permission() {
 244     JavaPermission p = {"java.lang.management.ManagementPermission",
 245                         "monitor", nullptr};
 246     return p;
 247   }
 248   virtual void execute(DCmdSource source, TRAPS);
 249 };
 250 
 251 class SystemGCDCmd : public DCmd {
 252 public:
 253   SystemGCDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 254     static const char* name() { return "GC.run"; }
 255     static const char* description() {
 256       return "Call java.lang.System.gc().";
 257     }
 258     static const char* impact() {
 259       return "Medium: Depends on Java heap size and content.";
 260     }
 261     virtual void execute(DCmdSource source, TRAPS);
 262 };
 263 
 264 class RunFinalizationDCmd : public DCmd {
 265 public:
 266   RunFinalizationDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 267     static const char* name() { return "GC.run_finalization"; }
 268     static const char* description() {
 269       return "Call java.lang.System.runFinalization().";
 270     }
 271     static const char* impact() {
 272       return "Medium: Depends on Java content.";
 273     }
 274     virtual void execute(DCmdSource source, TRAPS);
 275 };
 276 
 277 class HeapInfoDCmd : public DCmd {
 278 public:
 279   HeapInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 280   static const char* name() { return "GC.heap_info"; }
 281   static const char* description() {
 282     return "Provide generic Java heap information.";
 283   }
 284   static const char* impact() {
 285     return "Medium";
 286   }
 287   static const JavaPermission permission() {
 288     JavaPermission p = {"java.lang.management.ManagementPermission",
 289       "monitor", nullptr};
 290       return p;
 291   }
 292 
 293   virtual void execute(DCmdSource source, TRAPS);
 294 };
 295 
 296 class FinalizerInfoDCmd : public DCmd {
 297 public:
 298   FinalizerInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 299   static const char* name() { return "GC.finalizer_info"; }
 300   static const char* description() {
 301     return "Provide information about Java finalization queue.";
 302   }
 303   static const char* impact() {
 304     return "Medium";
 305   }
 306   static const JavaPermission permission() {
 307     JavaPermission p = {"java.lang.management.ManagementPermission",
 308       "monitor", nullptr};
 309       return p;
 310   }
 311 
 312   virtual void execute(DCmdSource source, TRAPS);
 313 };
 314 
 315 #if INCLUDE_SERVICES   // Heap dumping supported
 316 // See also: dump_heap in attachListener.cpp
 317 class HeapDumpDCmd : public DCmdWithParser {
 318 protected:
 319   DCmdArgument<char*> _filename;
 320   DCmdArgument<bool>  _all;
 321   DCmdArgument<jlong> _gzip;
 322   DCmdArgument<bool> _overwrite;
 323   DCmdArgument<jlong> _parallel;
 324 public:
 325   static int num_arguments() { return 5; }
 326   HeapDumpDCmd(outputStream* output, bool heap);
 327   static const char* name() {
 328     return "GC.heap_dump";
 329   }
 330   static const char* description() {
 331     return "Generate a HPROF format dump of the Java heap.";
 332   }
 333   static const char* impact() {
 334     return "High: Depends on Java heap size and content. "
 335            "Request a full GC unless the '-all' option is specified.";
 336   }
 337   static const JavaPermission permission() {
 338     JavaPermission p = {"java.lang.management.ManagementPermission",
 339                         "monitor", nullptr};
 340     return p;
 341   }
 342   virtual void execute(DCmdSource source, TRAPS);
 343 };
 344 #endif // INCLUDE_SERVICES
 345 
 346 // See also: inspectheap in attachListener.cpp
 347 class ClassHistogramDCmd : public DCmdWithParser {
 348 protected:
 349   DCmdArgument<bool> _all;
 350   DCmdArgument<jlong> _parallel_thread_num;
 351 public:
 352   static int num_arguments() { return 2; }
 353   ClassHistogramDCmd(outputStream* output, bool heap);
 354   static const char* name() {
 355     return "GC.class_histogram";
 356   }
 357   static const char* description() {
 358     return "Provide statistics about the Java heap usage.";
 359   }
 360   static const char* impact() {
 361     return "High: Depends on Java heap size and content.";
 362   }
 363   static const JavaPermission permission() {
 364     JavaPermission p = {"java.lang.management.ManagementPermission",
 365                         "monitor", nullptr};
 366     return p;
 367   }
 368   virtual void execute(DCmdSource source, TRAPS);
 369 };
 370 
 371 class ClassHierarchyDCmd : public DCmdWithParser {
 372 protected:
 373   DCmdArgument<bool> _print_interfaces; // true if inherited interfaces should be printed.
 374   DCmdArgument<bool> _print_subclasses; // true if subclasses of the specified classname should be printed.
 375   DCmdArgument<char*> _classname; // Optional single class name whose hierarchy should be printed.
 376 public:
 377   static int num_arguments() { return 3; }
 378   ClassHierarchyDCmd(outputStream* output, bool heap);
 379   static const char* name() {
 380     return "VM.class_hierarchy";
 381   }
 382   static const char* description() {
 383     return "Print a list of all loaded classes, indented to show the class hierarchy. "
 384            "The name of each class is followed by the ClassLoaderData* of its ClassLoader, "
 385            "or \"null\" if loaded by the bootstrap class loader.";
 386   }
 387   static const char* impact() {
 388       return "Medium: Depends on number of loaded classes.";
 389   }
 390   static const JavaPermission permission() {
 391     JavaPermission p = {"java.lang.management.ManagementPermission",
 392                         "monitor", nullptr};
 393     return p;
 394   }
 395   virtual void execute(DCmdSource source, TRAPS);
 396 };
 397 
 398 #if INCLUDE_CDS
 399 class DumpSharedArchiveDCmd: public DCmdWithParser {
 400 protected:
 401   DCmdArgument<char*> _suboption;   // option of VM.cds
 402   DCmdArgument<char*> _filename;    // file name, optional
 403 public:
 404   static int num_arguments() { return 2; }
 405   DumpSharedArchiveDCmd(outputStream* output, bool heap);
 406   static const char* name() {
 407     return "VM.cds";
 408   }
 409   static const char* description() {
 410     return "Dump a static or dynamic shared archive including all shareable classes";
 411   }
 412   static const char* impact() {
 413     return "Medium: Pause time depends on number of loaded classes";
 414   }
 415   static const JavaPermission permission() {
 416     JavaPermission p = {"java.lang.management.ManagementPermission",
 417                         "monitor", nullptr};
 418     return p;
 419   }
 420   virtual void execute(DCmdSource source, TRAPS);
 421 };
 422 #endif // INCLUDE_CDS
 423 
 424 // See also: thread_dump in attachListener.cpp
 425 class ThreadDumpDCmd : public DCmdWithParser {
 426 protected:
 427   DCmdArgument<bool> _locks;
 428   DCmdArgument<bool> _extended;
 429 public:
 430   static int num_arguments() { return 2; }
 431   ThreadDumpDCmd(outputStream* output, bool heap);
 432   static const char* name() { return "Thread.print"; }
 433   static const char* description() {
 434     return "Print all threads with stacktraces.";
 435   }
 436   static const char* impact() {
 437     return "Medium: Depends on the number of threads.";
 438   }
 439   static const JavaPermission permission() {
 440     JavaPermission p = {"java.lang.management.ManagementPermission",
 441                         "monitor", nullptr};
 442     return p;
 443   }
 444   virtual void execute(DCmdSource source, TRAPS);
 445 };
 446 
 447 // Enhanced JMX Agent support
 448 
 449 class JMXStartRemoteDCmd : public DCmdWithParser {
 450 
 451   // Explicitly list all properties that could be
 452   // passed to Agent.startRemoteManagementAgent()
 453   // com.sun.management is omitted
 454 
 455   DCmdArgument<char *> _config_file;
 456   DCmdArgument<char *> _jmxremote_host;
 457   DCmdArgument<char *> _jmxremote_port;
 458   DCmdArgument<char *> _jmxremote_rmi_port;
 459   DCmdArgument<char *> _jmxremote_ssl;
 460   DCmdArgument<char *> _jmxremote_registry_ssl;
 461   DCmdArgument<char *> _jmxremote_authenticate;
 462   DCmdArgument<char *> _jmxremote_password_file;
 463   DCmdArgument<char *> _jmxremote_access_file;
 464   DCmdArgument<char *> _jmxremote_login_config;
 465   DCmdArgument<char *> _jmxremote_ssl_enabled_cipher_suites;
 466   DCmdArgument<char *> _jmxremote_ssl_enabled_protocols;
 467   DCmdArgument<char *> _jmxremote_ssl_need_client_auth;
 468   DCmdArgument<char *> _jmxremote_ssl_config_file;
 469 
 470   // JDP support
 471   // Keep autodiscovery char* not bool to pass true/false
 472   // as property value to java level.
 473   DCmdArgument<char *> _jmxremote_autodiscovery;
 474   DCmdArgument<jlong>  _jdp_port;
 475   DCmdArgument<char *> _jdp_address;
 476   DCmdArgument<char *> _jdp_source_addr;
 477   DCmdArgument<jlong>  _jdp_ttl;
 478   DCmdArgument<jlong>  _jdp_pause;
 479   DCmdArgument<char *> _jdp_name;
 480 
 481 public:
 482   static int num_arguments() { return 21; }
 483 
 484   JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
 485 
 486   static const char *name() {
 487     return "ManagementAgent.start";
 488   }
 489 
 490   static const char *description() {
 491     return "Start remote management agent.";
 492   }
 493 
 494   virtual void execute(DCmdSource source, TRAPS);
 495 };
 496 
 497 class JMXStartLocalDCmd : public DCmd {
 498 
 499   // Explicitly request start of local agent,
 500   // it will not be started by start dcmd
 501 
 502 
 503 public:
 504   JMXStartLocalDCmd(outputStream *output, bool heap_allocated);
 505 
 506   static const char *name() {
 507     return "ManagementAgent.start_local";
 508   }
 509 
 510   static const char *description() {
 511     return "Start local management agent.";
 512   }
 513 
 514   virtual void execute(DCmdSource source, TRAPS);
 515 
 516 };
 517 
 518 class JMXStopRemoteDCmd : public DCmd {
 519 public:
 520   JMXStopRemoteDCmd(outputStream *output, bool heap_allocated) :
 521   DCmd(output, heap_allocated) {
 522     // Do Nothing
 523   }
 524 
 525   static const char *name() {
 526     return "ManagementAgent.stop";
 527   }
 528 
 529   static const char *description() {
 530     return "Stop remote management agent.";
 531   }
 532 
 533   virtual void execute(DCmdSource source, TRAPS);
 534 };
 535 
 536 // Print the JMX system status
 537 class JMXStatusDCmd : public DCmd {
 538 public:
 539   JMXStatusDCmd(outputStream *output, bool heap_allocated);
 540 
 541   static const char *name() {
 542     return "ManagementAgent.status";
 543   }
 544 
 545   static const char *description() {
 546     return "Print the management agent status.";
 547   }
 548 
 549   static const JavaPermission permission() {
 550     JavaPermission p = {"java.lang.management.ManagementPermission",
 551                         "monitor", nullptr};
 552     return p;
 553   }
 554 
 555   virtual void execute(DCmdSource source, TRAPS);
 556 
 557 };
 558 
 559 class CompileQueueDCmd : public DCmd {
 560 public:
 561   CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
 562   static const char* name() {
 563     return "Compiler.queue";
 564   }
 565   static const char* description() {
 566     return "Print methods queued for compilation.";
 567   }
 568   static const char* impact() {
 569     return "Low";
 570   }
 571   static const JavaPermission permission() {
 572     JavaPermission p = {"java.lang.management.ManagementPermission",
 573                         "monitor", nullptr};
 574     return p;
 575   }
 576   virtual void execute(DCmdSource source, TRAPS);
 577 };
 578 
 579 #ifdef LINUX
 580 class PerfMapDCmd : public DCmdWithParser {
 581 protected:
 582   DCmdArgument<char*> _filename;
 583 public:
 584   static int num_arguments() { return 1; }
 585   PerfMapDCmd(outputStream* output, bool heap);
 586   static const char* name() {
 587     return "Compiler.perfmap";
 588   }
 589   static const char* description() {
 590     return "Write map file for Linux perf tool.";
 591   }
 592   static const char* impact() {
 593     return "Low";
 594   }
 595   static const JavaPermission permission() {
 596     JavaPermission p = {"java.lang.management.ManagementPermission",
 597                         "monitor", nullptr};
 598     return p;
 599   }
 600   virtual void execute(DCmdSource source, TRAPS);
 601 };
 602 #endif // LINUX
 603 
 604 class CodeListDCmd : public DCmd {
 605 public:
 606   CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
 607   static const char* name() {
 608     return "Compiler.codelist";
 609   }
 610   static const char* description() {
 611     return "Print all compiled methods in code cache that are alive";
 612   }
 613   static const char* impact() {
 614     return "Medium";
 615   }
 616   static const JavaPermission permission() {
 617     JavaPermission p = {"java.lang.management.ManagementPermission",
 618                         "monitor", nullptr};
 619     return p;
 620   }
 621   virtual void execute(DCmdSource source, TRAPS);
 622 };
 623 
 624 class CodeCacheDCmd : public DCmd {
 625 public:
 626   CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
 627   static const char* name() {
 628     return "Compiler.codecache";
 629   }
 630   static const char* description() {
 631     return "Print code cache layout and bounds.";
 632   }
 633   static const char* impact() {
 634     return "Low";
 635   }
 636   static const JavaPermission permission() {
 637     JavaPermission p = {"java.lang.management.ManagementPermission",
 638                         "monitor", nullptr};
 639     return p;
 640   }
 641   virtual void execute(DCmdSource source, TRAPS);
 642 };
 643 
 644 //---<  BEGIN  >--- CodeHeap State Analytics.
 645 class CodeHeapAnalyticsDCmd : public DCmdWithParser {
 646 protected:
 647   DCmdArgument<char*> _function;
 648   DCmdArgument<jlong> _granularity;
 649 public:
 650   static int num_arguments() { return 2; }
 651   CodeHeapAnalyticsDCmd(outputStream* output, bool heap);
 652   static const char* name() {
 653     return "Compiler.CodeHeap_Analytics";
 654   }
 655   static const char* description() {
 656     return "Print CodeHeap analytics";
 657   }
 658   static const char* impact() {
 659     return "Low: Depends on code heap size and content. "
 660            "Holds CodeCache_lock during analysis step, usually sub-second duration.";
 661   }
 662   static const JavaPermission permission() {
 663     JavaPermission p = {"java.lang.management.ManagementPermission",
 664                         "monitor", nullptr};
 665     return p;
 666   }
 667   virtual void execute(DCmdSource source, TRAPS);
 668 };
 669 //---<  END  >--- CodeHeap State Analytics.
 670 
 671 class CompilerDirectivesPrintDCmd : public DCmd {
 672 public:
 673   CompilerDirectivesPrintDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
 674   static const char* name() {
 675     return "Compiler.directives_print";
 676   }
 677   static const char* description() {
 678     return "Print all active compiler directives.";
 679   }
 680   static const char* impact() {
 681     return "Low";
 682   }
 683   static const JavaPermission permission() {
 684     JavaPermission p = {"java.lang.management.ManagementPermission",
 685                         "monitor", nullptr};
 686     return p;
 687   }
 688   virtual void execute(DCmdSource source, TRAPS);
 689 };
 690 
 691 class CompilerDirectivesRemoveDCmd : public DCmdWithParser {
 692 protected:
 693   DCmdArgument<bool> _refresh; // true if update should be forced after directives changes.
 694 public:
 695   static int num_arguments() { return 1; }
 696   CompilerDirectivesRemoveDCmd(outputStream* output, bool heap);
 697   static const char* name() {
 698     return "Compiler.directives_remove";
 699   }
 700   static const char* description() {
 701     return "Remove latest added compiler directive.";
 702   }
 703   static const char* impact() {
 704     return "Low";
 705   }
 706   static const JavaPermission permission() {
 707     JavaPermission p = {"java.lang.management.ManagementPermission",
 708                         "control", nullptr};
 709     return p;
 710   }
 711   virtual void execute(DCmdSource source, TRAPS);
 712 };
 713 
 714 class CompilerDirectivesAddDCmd : public DCmdWithParser {
 715 protected:
 716   DCmdArgument<char*> _filename;
 717   DCmdArgument<bool> _refresh; // true if update should be forced after directives changes.
 718 public:
 719   static int num_arguments() { return 2; }
 720   CompilerDirectivesAddDCmd(outputStream* output, bool heap);
 721   static const char* name() {
 722     return "Compiler.directives_add";
 723   }
 724   static const char* description() {
 725     return "Add compiler directives from file.";
 726   }
 727   static const char* impact() {
 728     return "Low";
 729   }
 730   static const JavaPermission permission() {
 731     JavaPermission p = {"java.lang.management.ManagementPermission",
 732                         "control", nullptr};
 733     return p;
 734   }
 735   virtual void execute(DCmdSource source, TRAPS);
 736 };
 737 
 738 class CompilerDirectivesReplaceDCmd : public DCmdWithParser {
 739 protected:
 740   DCmdArgument<char*> _filename;
 741   DCmdArgument<bool> _refresh; // true if update should be forced after directives changes.
 742 public:
 743   static int num_arguments() { return 2; }
 744   CompilerDirectivesReplaceDCmd(outputStream* output, bool heap);
 745   static const char* name() {
 746     return "Compiler.directives_replace";
 747   }
 748   static const char* description() {
 749     return "Clear directives stack, and load new compiler directives from file.";
 750   }
 751   static const char* impact() {
 752     return "Low";
 753   }
 754   static const JavaPermission permission() {
 755     JavaPermission p = {"java.lang.management.ManagementPermission",
 756                         "monitor", NULL};
 757     return p;
 758   }
 759   virtual void execute(DCmdSource source, TRAPS);
 760 };
 761 
 762 class CompilerDirectivesClearDCmd : public DCmdWithParser {
 763 protected:
 764   DCmdArgument<bool> _refresh; // true if update should be forced after directives changes.
 765 public:
 766   static int num_arguments() { return 1; }
 767   CompilerDirectivesClearDCmd(outputStream* output, bool heap);
 768   static const char* name() {
 769     return "Compiler.directives_clear";
 770   }
 771   static const char* description() {
 772     return "Remove all compiler directives.";
 773   }
 774   static const char* impact() {
 775     return "Low";
 776   }
 777   static const JavaPermission permission() {
 778     JavaPermission p = {"java.lang.management.ManagementPermission",
 779                         "control", nullptr};
 780     return p;
 781   }
 782   virtual void execute(DCmdSource source, TRAPS);
 783 };
 784 
 785 ///////////////////////////////////////////////////////////////////////
 786 //
 787 // jcmd command support for symbol table, string table and system dictionary dumping:
 788 //   VM.symboltable -verbose: for dumping the symbol table
 789 //   VM.stringtable -verbose: for dumping the string table
 790 //   VM.systemdictionary -verbose: for dumping the system dictionary table
 791 //
 792 class VM_DumpHashtable : public VM_Operation {
 793 private:
 794   outputStream* _out;
 795   int _which;
 796   bool _verbose;
 797 public:
 798   enum {
 799     DumpSymbols = 1 << 0,
 800     DumpStrings = 1 << 1,
 801     DumpSysDict = 1 << 2  // not implemented yet
 802   };
 803   VM_DumpHashtable(outputStream* out, int which, bool verbose) {
 804     _out = out;
 805     _which = which;
 806     _verbose = verbose;
 807   }
 808 
 809   virtual VMOp_Type type() const { return VMOp_DumpHashtable; }
 810 
 811   virtual void doit() {
 812     switch (_which) {
 813     case DumpSymbols:
 814       SymbolTable::dump(_out, _verbose);
 815       break;
 816     case DumpStrings:
 817       StringTable::dump(_out, _verbose);
 818       break;
 819     case DumpSysDict:
 820       SystemDictionary::dump(_out, _verbose);
 821       break;
 822     default:
 823       ShouldNotReachHere();
 824     }
 825   }
 826 };
 827 
 828 class SymboltableDCmd : public DCmdWithParser {
 829 protected:
 830   DCmdArgument<bool> _verbose;
 831 public:
 832   static int num_arguments() { return 1; }
 833   SymboltableDCmd(outputStream* output, bool heap);
 834   static const char* name() {
 835     return "VM.symboltable";
 836   }
 837   static const char* description() {
 838     return "Dump symbol table.";
 839   }
 840   static const char* impact() {
 841     return "Medium: Depends on Java content.";
 842   }
 843   static const JavaPermission permission() {
 844     JavaPermission p = {"java.lang.management.ManagementPermission",
 845                         "monitor", nullptr};
 846     return p;
 847   }
 848   virtual void execute(DCmdSource source, TRAPS);
 849 };
 850 
 851 class StringtableDCmd : public DCmdWithParser {
 852 protected:
 853   DCmdArgument<bool> _verbose;
 854 public:
 855   static int num_arguments() { return 1; }
 856   StringtableDCmd(outputStream* output, bool heap);
 857   static const char* name() {
 858     return "VM.stringtable";
 859   }
 860   static const char* description() {
 861     return "Dump string table.";
 862   }
 863   static const char* impact() {
 864     return "Medium: Depends on Java content.";
 865   }
 866   static const JavaPermission permission() {
 867     JavaPermission p = {"java.lang.management.ManagementPermission",
 868                         "monitor", nullptr};
 869     return p;
 870   }
 871   virtual void execute(DCmdSource source, TRAPS);
 872 };
 873 
 874 class SystemDictionaryDCmd : public DCmdWithParser {
 875 protected:
 876   DCmdArgument<bool> _verbose;
 877 public:
 878   static int num_arguments() { return 1; }
 879   SystemDictionaryDCmd(outputStream* output, bool heap);
 880   static const char* name() {
 881     return "VM.systemdictionary";
 882   }
 883   static const char* description() {
 884     return "Prints the statistics for dictionary hashtable sizes and bucket length";
 885   }
 886   static const char* impact() {
 887       return "Medium: Depends on Java content.";
 888   }
 889   static const JavaPermission permission() {
 890     JavaPermission p = {"java.lang.management.ManagementPermission",
 891                         "monitor", nullptr};
 892     return p;
 893   }
 894   virtual void execute(DCmdSource source, TRAPS);
 895 };
 896 
 897 class ClassesDCmd : public DCmdWithParser {
 898 protected:
 899   DCmdArgument<bool> _verbose;
 900 public:
 901   static int num_arguments() { return 1; }
 902   ClassesDCmd(outputStream* output, bool heap);
 903   static const char* name() {
 904     return "VM.classes";
 905   }
 906   static const char* description() {
 907     return "Print all loaded classes";
 908   }
 909   static const char* impact() {
 910       return "Medium: Depends on number of loaded classes.";
 911   }
 912   static const JavaPermission permission() {
 913     JavaPermission p = {"java.lang.management.ManagementPermission",
 914                         "monitor", nullptr};
 915     return p;
 916   }
 917   virtual void execute(DCmdSource source, TRAPS);
 918 };
 919 
 920 #if INCLUDE_JVMTI
 921 class DebugOnCmdStartDCmd : public DCmd {
 922 public:
 923   DebugOnCmdStartDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
 924   static const char* name() {
 925     return "VM.start_java_debugging";
 926   }
 927   static const char* description() {
 928     return "Starts up the Java debugging if the jdwp agentlib was enabled with the option onjcmd=y.";
 929   }
 930   static const char* impact() {
 931     return "High: Switches the VM into Java debug mode.";
 932   }
 933   static const JavaPermission permission() {
 934     JavaPermission p = { "java.lang.management.ManagementPermission", "control", nullptr };
 935     return p;
 936   }
 937   virtual void execute(DCmdSource source, TRAPS);
 938 };
 939 #endif // INCLUDE_JVMTI
 940 
 941 class EventLogDCmd : public DCmdWithParser {
 942 protected:
 943   DCmdArgument<char*> _log;
 944   DCmdArgument<char*> _max;
 945 public:
 946   static int num_arguments() { return 2; }
 947   EventLogDCmd(outputStream* output, bool heap);
 948   static const char* name() {
 949     return "VM.events";
 950   }
 951   static const char* description() {
 952     return "Print VM event logs";
 953   }
 954   static const char* impact() {
 955     return "Low: Depends on event log size. ";
 956   }
 957   static const JavaPermission permission() {
 958     JavaPermission p = {"java.lang.management.ManagementPermission",
 959                         "monitor", nullptr};
 960     return p;
 961   }
 962   virtual void execute(DCmdSource source, TRAPS);
 963 };
 964 
 965 class ThreadDumpToFileDCmd : public DCmdWithParser {
 966 private:
 967   void dumpToFile(Symbol* name, Symbol* signature, const char* path, bool overwrite, TRAPS);
 968 protected:
 969   DCmdArgument<bool> _overwrite;
 970   DCmdArgument<char*> _format;
 971   DCmdArgument<char*> _filepath;
 972 public:
 973   static int num_arguments() { return 3; }
 974   ThreadDumpToFileDCmd(outputStream *output, bool heap);
 975   static const char *name() {
 976     return "Thread.dump_to_file";
 977   }
 978   static const char *description() {
 979     return "Dump threads, with stack traces, to a file in plain text or JSON format.";
 980   }
 981   static const char* impact() {
 982     return "Medium: Depends on the number of threads.";
 983   }
 984   static const JavaPermission permission() {
 985     JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", nullptr};
 986     return p;
 987   }
 988   virtual void execute(DCmdSource source, TRAPS);
 989 };
 990 
 991 class VThreadSchedulerDCmd : public DCmd {
 992 public:
 993   VThreadSchedulerDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
 994   static const char* name() {
 995     return "Thread.vthread_scheduler";
 996   }
 997   static const char* description() {
 998     return "Print virtual thread scheduler info.";
 999   }
1000   static const char* impact() { return "Low"; }
1001   virtual void execute(DCmdSource source, TRAPS);
1002 };
1003 
1004 class CompilationMemoryStatisticDCmd: public DCmdWithParser {
1005 protected:
1006   DCmdArgument<bool> _human_readable;
1007   DCmdArgument<MemorySizeArgument> _minsize;
1008 public:
1009   static int num_arguments() { return 2; }
1010   CompilationMemoryStatisticDCmd(outputStream* output, bool heap);
1011   static const char* name() {
1012     return "Compiler.memory";
1013   }
1014   static const char* description() {
1015     return "Print compilation footprint";
1016   }
1017   static const char* impact() {
1018     return "Medium: Pause time depends on number of compiled methods";
1019   }
1020   static const JavaPermission permission() {
1021     JavaPermission p = {"java.lang.management.ManagementPermission",
1022                         "monitor", nullptr};
1023     return p;
1024   }
1025   virtual void execute(DCmdSource source, TRAPS);
1026 };
1027 
1028 #ifdef LINUX
1029 
1030 class SystemMapDCmd : public DCmdWithParser {
1031   DCmdArgument<bool> _human_readable;
1032 public:
1033   static int num_arguments() { return 1; }
1034   SystemMapDCmd(outputStream* output, bool heap);
1035   static const char* name() { return "System.map"; }
1036   static const char* description() {
1037     return "Prints an annotated process memory map of the VM process (linux only).";
1038   }
1039   static const char* impact() { return "Low"; }
1040   static const JavaPermission permission() {
1041     JavaPermission p = {"java.lang.management.ManagementPermission",
1042                         "control", nullptr};
1043     return p;
1044   }
1045   virtual void execute(DCmdSource source, TRAPS);
1046 };
1047 
1048 class SystemDumpMapDCmd : public DCmdWithParser {
1049   DCmdArgument<bool> _human_readable;
1050   DCmdArgument<char*> _filename;
1051 public:
1052   static int num_arguments() { return 2; }
1053   SystemDumpMapDCmd(outputStream* output, bool heap);
1054   static const char* name() { return "System.dump_map"; }
1055   static const char* description() {
1056     return "Dumps an annotated process memory map to an output file (linux only).";
1057   }
1058   static const char* impact() { return "Low"; }
1059   static const JavaPermission permission() {
1060     JavaPermission p = {"java.lang.management.ManagementPermission",
1061                         "control", nullptr};
1062     return p;
1063   }
1064   virtual void execute(DCmdSource source, TRAPS);
1065 };
1066 
1067 #endif // LINUX
1068 
1069 #endif // SHARE_SERVICES_DIAGNOSTICCOMMAND_HPP