1 /* 2 * Copyright (c) 2011, 2015, 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_VM_SERVICES_DIAGNOSTICCOMMAND_HPP 26 #define SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP 27 28 #include "classfile/vmSymbols.hpp" 29 #include "runtime/arguments.hpp" 30 #include "runtime/os.hpp" 31 #include "runtime/vmThread.hpp" 32 #include "services/diagnosticArgument.hpp" 33 #include "services/diagnosticCommand.hpp" 34 #include "services/diagnosticCommand_ext.hpp" 35 #include "services/diagnosticFramework.hpp" 36 #include "utilities/macros.hpp" 37 #include "utilities/ostream.hpp" 38 #include "oops/method.hpp" 39 40 class HelpDCmd : public DCmdWithParser { 41 protected: 42 DCmdArgument<bool> _all; 43 DCmdArgument<char*> _cmd; 44 public: 45 HelpDCmd(outputStream* output, bool heap); 46 static const char* name() { return "help"; } 47 static const char* description() { 48 return "For more information about a specific command use 'help <command>'. " 49 "With no argument this will show a list of available commands. " 50 "'help all' will show help for all commands."; 51 } 52 static const char* impact() { return "Low"; } 53 static int num_arguments(); 54 virtual void execute(DCmdSource source, TRAPS); 55 }; 56 57 class VersionDCmd : public DCmd { 58 public: 59 VersionDCmd(outputStream* output, bool heap) : DCmd(output,heap) { } 60 static const char* name() { return "VM.version"; } 61 static const char* description() { 62 return "Print JVM version information."; 63 } 64 static const char* impact() { return "Low"; } 65 static const JavaPermission permission() { 66 JavaPermission p = {"java.util.PropertyPermission", 67 "java.vm.version", "read"}; 68 return p; 69 } 70 static int num_arguments() { return 0; } 71 virtual void execute(DCmdSource source, TRAPS); 72 }; 73 74 class CommandLineDCmd : public DCmd { 75 public: 76 CommandLineDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 77 static const char* name() { return "VM.command_line"; } 78 static const char* description() { 79 return "Print the command line used to start this VM instance."; 80 } 81 static const char* impact() { return "Low"; } 82 static const JavaPermission permission() { 83 JavaPermission p = {"java.lang.management.ManagementPermission", 84 "monitor", NULL}; 85 return p; 86 } 87 static int num_arguments() { return 0; } 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 static int num_arguments() { return 0; } 110 virtual void execute(DCmdSource source, TRAPS); 111 }; 112 113 // See also: print_flag in attachListener.cpp 114 class PrintVMFlagsDCmd : public DCmdWithParser { 115 protected: 116 DCmdArgument<bool> _all; 117 public: 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", NULL}; 129 return p; 130 } 131 static int num_arguments(); 132 virtual void execute(DCmdSource source, TRAPS); 133 }; 134 135 class SetVMFlagDCmd : public DCmdWithParser { 136 protected: 137 DCmdArgument<char*> _flag; 138 DCmdArgument<char*> _value; 139 140 public: 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", NULL}; 152 return p; 153 } 154 static int num_arguments(); 155 virtual void execute(DCmdSource source, TRAPS); 156 }; 157 158 class JVMTIDataDumpDCmd : public DCmd { 159 public: 160 JVMTIDataDumpDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 161 static const char* name() { return "JVMTI.data_dump"; } 162 static const char* description() { 163 return "Signal the JVM to do a data-dump request for JVMTI."; 164 } 165 static const char* impact() { 166 return "High"; 167 } 168 static const JavaPermission permission() { 169 JavaPermission p = {"java.lang.management.ManagementPermission", 170 "monitor", NULL}; 171 return p; 172 } 173 static int num_arguments() { return 0; } 174 virtual void execute(DCmdSource source, TRAPS); 175 }; 176 177 class JVMTIAgentLoadDCmd : public DCmdWithParser { 178 protected: 179 DCmdArgument<char*> _libpath; 180 DCmdArgument<char*> _option; 181 public: 182 JVMTIAgentLoadDCmd(outputStream* output, bool heap); 183 static const char* name() { return "JVMTI.agent_load"; } 184 static const char* description() { 185 return "Load JVMTI native agent."; 186 } 187 static const char* impact() { return "Low"; } 188 static const JavaPermission permission() { 189 JavaPermission p = {"java.lang.management.ManagementPermission", 190 "control", NULL}; 191 return p; 192 } 193 static int num_arguments(); 194 virtual void execute(DCmdSource source, TRAPS); 195 }; 196 197 class JVMTIJavaAgentLoadDCmd : public DCmdWithParser { 198 protected: 199 DCmdArgument<char*> _libpath; 200 DCmdArgument<char*> _option; 201 public: 202 JVMTIJavaAgentLoadDCmd(outputStream* output, bool heap); 203 static const char* name() { return "JVMTI.javaagent_load"; } 204 static const char* description() { 205 return "Load JVMTI java agent."; 206 } 207 static const char* impact() { return "Low"; } 208 static const JavaPermission permission() { 209 JavaPermission p = {"java.lang.management.ManagementPermission", 210 "control", NULL}; 211 return p; 212 } 213 static int num_arguments(); 214 virtual void execute(DCmdSource source, TRAPS); 215 }; 216 217 class VMDynamicLibrariesDCmd : public DCmd { 218 public: 219 VMDynamicLibrariesDCmd(outputStream* output, bool heap); 220 static const char* name() { 221 return "VM.dynlibs"; 222 } 223 static const char* description() { 224 return "Print loaded dynamic libraries."; 225 } 226 static const char* impact() { 227 return "Low"; 228 } 229 static const JavaPermission permission() { 230 JavaPermission p = {"java.lang.management.ManagementPermission", 231 "monitor", NULL}; 232 return p; 233 } 234 static int num_arguments() { 235 return 0; 236 }; 237 virtual void execute(DCmdSource source, TRAPS); 238 }; 239 240 class VMUptimeDCmd : public DCmdWithParser { 241 protected: 242 DCmdArgument<bool> _date; 243 public: 244 VMUptimeDCmd(outputStream* output, bool heap); 245 static const char* name() { return "VM.uptime"; } 246 static const char* description() { 247 return "Print VM uptime."; 248 } 249 static const char* impact() { 250 return "Low"; 251 } 252 static int num_arguments(); 253 virtual void execute(DCmdSource source, TRAPS); 254 }; 255 256 class VMInfoDCmd : public DCmd { 257 public: 258 VMInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 259 static const char* name() { return "VM.info"; } 260 static const char* description() { 261 return "Print information about JVM environment and status."; 262 } 263 static const char* impact() { return "Low"; } 264 static const JavaPermission permission() { 265 JavaPermission p = {"java.lang.management.ManagementPermission", 266 "monitor", NULL}; 267 return p; 268 } 269 static int num_arguments() { return 0; } 270 virtual void execute(DCmdSource source, TRAPS); 271 }; 272 273 class SystemGCDCmd : public DCmd { 274 public: 275 SystemGCDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 276 static const char* name() { return "GC.run"; } 277 static const char* description() { 278 return "Call java.lang.System.gc()."; 279 } 280 static const char* impact() { 281 return "Medium: Depends on Java heap size and content."; 282 } 283 static int num_arguments() { return 0; } 284 virtual void execute(DCmdSource source, TRAPS); 285 }; 286 287 class RunFinalizationDCmd : public DCmd { 288 public: 289 RunFinalizationDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 290 static const char* name() { return "GC.run_finalization"; } 291 static const char* description() { 292 return "Call java.lang.System.runFinalization()."; 293 } 294 static const char* impact() { 295 return "Medium: Depends on Java content."; 296 } 297 static int num_arguments() { return 0; } 298 virtual void execute(DCmdSource source, TRAPS); 299 }; 300 301 class HeapInfoDCmd : public DCmd { 302 public: 303 HeapInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 304 static const char* name() { return "GC.heap_info"; } 305 static const char* description() { 306 return "Provide generic Java heap information."; 307 } 308 static const char* impact() { 309 return "Medium"; 310 } 311 static int num_arguments() { return 0; } 312 static const JavaPermission permission() { 313 JavaPermission p = {"java.lang.management.ManagementPermission", 314 "monitor", NULL}; 315 return p; 316 } 317 318 virtual void execute(DCmdSource source, TRAPS); 319 }; 320 321 class FinalizerInfoDCmd : public DCmd { 322 public: 323 FinalizerInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } 324 static const char* name() { return "GC.finalizer_info"; } 325 static const char* description() { 326 return "Provide information about Java finalization queue."; 327 } 328 static const char* impact() { 329 return "Medium"; 330 } 331 static int num_arguments() { return 0; } 332 static const JavaPermission permission() { 333 JavaPermission p = {"java.lang.management.ManagementPermission", 334 "monitor", NULL}; 335 return p; 336 } 337 338 virtual void execute(DCmdSource source, TRAPS); 339 }; 340 341 #if INCLUDE_SERVICES // Heap dumping supported 342 // See also: dump_heap in attachListener.cpp 343 class HeapDumpDCmd : public DCmdWithParser { 344 protected: 345 DCmdArgument<char*> _filename; 346 DCmdArgument<bool> _all; 347 public: 348 HeapDumpDCmd(outputStream* output, bool heap); 349 static const char* name() { 350 return "GC.heap_dump"; 351 } 352 static const char* description() { 353 return "Generate a HPROF format dump of the Java heap."; 354 } 355 static const char* impact() { 356 return "High: Depends on Java heap size and content. " 357 "Request a full GC unless the '-all' option is specified."; 358 } 359 static const JavaPermission permission() { 360 JavaPermission p = {"java.lang.management.ManagementPermission", 361 "monitor", NULL}; 362 return p; 363 } 364 static int num_arguments(); 365 virtual void execute(DCmdSource source, TRAPS); 366 }; 367 #endif // INCLUDE_SERVICES 368 369 // See also: inspectheap in attachListener.cpp 370 class ClassHistogramDCmd : public DCmdWithParser { 371 protected: 372 DCmdArgument<bool> _all; 373 public: 374 ClassHistogramDCmd(outputStream* output, bool heap); 375 static const char* name() { 376 return "GC.class_histogram"; 377 } 378 static const char* description() { 379 return "Provide statistics about the Java heap usage."; 380 } 381 static const char* impact() { 382 return "High: Depends on Java heap size and content."; 383 } 384 static const JavaPermission permission() { 385 JavaPermission p = {"java.lang.management.ManagementPermission", 386 "monitor", NULL}; 387 return p; 388 } 389 static int num_arguments(); 390 virtual void execute(DCmdSource source, TRAPS); 391 }; 392 393 class ClassStatsDCmd : public DCmdWithParser { 394 protected: 395 DCmdArgument<bool> _all; 396 DCmdArgument<bool> _csv; 397 DCmdArgument<bool> _help; 398 DCmdArgument<char*> _columns; 399 public: 400 ClassStatsDCmd(outputStream* output, bool heap); 401 static const char* name() { 402 return "GC.class_stats"; 403 } 404 static const char* description() { 405 return "Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions."; 406 } 407 static const char* impact() { 408 return "High: Depends on Java heap size and content."; 409 } 410 static int num_arguments(); 411 virtual void execute(DCmdSource source, TRAPS); 412 }; 413 414 415 class ClassHierarchyDCmd : public DCmdWithParser { 416 protected: 417 DCmdArgument<bool> _print_interfaces; // true if inherited interfaces should be printed. 418 DCmdArgument<bool> _print_subclasses; // true if subclasses of the specified classname should be printed. 419 DCmdArgument<char*> _classname; // Optional single class name whose hierarchy should be printed. 420 public: 421 ClassHierarchyDCmd(outputStream* output, bool heap); 422 static const char* name() { 423 return "VM.class_hierarchy"; 424 } 425 static const char* description() { 426 return "Print a list of all loaded classes, indented to show the class hiearchy. " 427 "The name of each class is followed by the ClassLoaderData* of its ClassLoader, " 428 "or \"null\" if loaded by the bootstrap class loader."; 429 } 430 static const char* impact() { 431 return "Medium: Depends on number of loaded classes."; 432 } 433 static const JavaPermission permission() { 434 JavaPermission p = {"java.lang.management.ManagementPermission", 435 "monitor", NULL}; 436 return p; 437 } 438 static int num_arguments(); 439 virtual void execute(DCmdSource source, TRAPS); 440 }; 441 442 class TouchedMethodsDCmd : public DCmdWithParser { 443 public: 444 TouchedMethodsDCmd(outputStream* output, bool heap); 445 static const char* name() { 446 return "VM.print_touched_methods"; 447 } 448 static const char* description() { 449 return "Print all methods that have ever been touched during the lifetime of this JVM."; 450 } 451 static const char* impact() { 452 return "Medium: Depends on Java content."; 453 } 454 static int num_arguments(); 455 virtual void execute(DCmdSource source, TRAPS); 456 }; 457 458 // See also: thread_dump in attachListener.cpp 459 class ThreadDumpDCmd : public DCmdWithParser { 460 protected: 461 DCmdArgument<bool> _locks; 462 public: 463 ThreadDumpDCmd(outputStream* output, bool heap); 464 static const char* name() { return "Thread.print"; } 465 static const char* description() { 466 return "Print all threads with stacktraces."; 467 } 468 static const char* impact() { 469 return "Medium: Depends on the number of threads."; 470 } 471 static const JavaPermission permission() { 472 JavaPermission p = {"java.lang.management.ManagementPermission", 473 "monitor", NULL}; 474 return p; 475 } 476 static int num_arguments(); 477 virtual void execute(DCmdSource source, TRAPS); 478 }; 479 480 // Enhanced JMX Agent support 481 482 class JMXStartRemoteDCmd : public DCmdWithParser { 483 484 // Explicitly list all properties that could be 485 // passed to Agent.startRemoteManagementAgent() 486 // com.sun.management is omitted 487 488 DCmdArgument<char *> _config_file; 489 DCmdArgument<char *> _jmxremote_host; 490 DCmdArgument<char *> _jmxremote_port; 491 DCmdArgument<char *> _jmxremote_rmi_port; 492 DCmdArgument<char *> _jmxremote_ssl; 493 DCmdArgument<char *> _jmxremote_registry_ssl; 494 DCmdArgument<char *> _jmxremote_authenticate; 495 DCmdArgument<char *> _jmxremote_password_file; 496 DCmdArgument<char *> _jmxremote_access_file; 497 DCmdArgument<char *> _jmxremote_login_config; 498 DCmdArgument<char *> _jmxremote_ssl_enabled_cipher_suites; 499 DCmdArgument<char *> _jmxremote_ssl_enabled_protocols; 500 DCmdArgument<char *> _jmxremote_ssl_need_client_auth; 501 DCmdArgument<char *> _jmxremote_ssl_config_file; 502 503 // JDP support 504 // Keep autodiscovery char* not bool to pass true/false 505 // as property value to java level. 506 DCmdArgument<char *> _jmxremote_autodiscovery; 507 DCmdArgument<jlong> _jdp_port; 508 DCmdArgument<char *> _jdp_address; 509 DCmdArgument<char *> _jdp_source_addr; 510 DCmdArgument<jlong> _jdp_ttl; 511 DCmdArgument<jlong> _jdp_pause; 512 DCmdArgument<char *> _jdp_name; 513 514 public: 515 JMXStartRemoteDCmd(outputStream *output, bool heap_allocated); 516 517 static const char *name() { 518 return "ManagementAgent.start"; 519 } 520 521 static const char *description() { 522 return "Start remote management agent."; 523 } 524 525 static int num_arguments(); 526 527 virtual void execute(DCmdSource source, TRAPS); 528 529 }; 530 531 class JMXStartLocalDCmd : public DCmd { 532 533 // Explicitly request start of local agent, 534 // it will not be started by start dcmd 535 536 537 public: 538 JMXStartLocalDCmd(outputStream *output, bool heap_allocated); 539 540 static const char *name() { 541 return "ManagementAgent.start_local"; 542 } 543 544 static const char *description() { 545 return "Start local management agent."; 546 } 547 548 virtual void execute(DCmdSource source, TRAPS); 549 550 }; 551 552 class JMXStopRemoteDCmd : public DCmd { 553 public: 554 JMXStopRemoteDCmd(outputStream *output, bool heap_allocated) : 555 DCmd(output, heap_allocated) { 556 // Do Nothing 557 } 558 559 static const char *name() { 560 return "ManagementAgent.stop"; 561 } 562 563 static const char *description() { 564 return "Stop remote management agent."; 565 } 566 567 virtual void execute(DCmdSource source, TRAPS); 568 }; 569 570 // Print the JMX system status 571 class JMXStatusDCmd : public DCmd { 572 public: 573 JMXStatusDCmd(outputStream *output, bool heap_allocated); 574 575 static const char *name() { 576 return "ManagementAgent.status"; 577 } 578 579 static const char *description() { 580 return "Print the management agent status."; 581 } 582 583 static const JavaPermission permission() { 584 JavaPermission p = {"java.lang.management.ManagementPermission", 585 "monitor", NULL}; 586 return p; 587 } 588 589 virtual void execute(DCmdSource source, TRAPS); 590 591 }; 592 593 class CompileQueueDCmd : public DCmd { 594 public: 595 CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} 596 static const char* name() { 597 return "Compiler.queue"; 598 } 599 static const char* description() { 600 return "Print methods queued for compilation."; 601 } 602 static const char* impact() { 603 return "Low"; 604 } 605 static const JavaPermission permission() { 606 JavaPermission p = {"java.lang.management.ManagementPermission", 607 "monitor", NULL}; 608 return p; 609 } 610 static int num_arguments() { return 0; } 611 virtual void execute(DCmdSource source, TRAPS); 612 }; 613 614 class CodeListDCmd : public DCmd { 615 public: 616 CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} 617 static const char* name() { 618 return "Compiler.codelist"; 619 } 620 static const char* description() { 621 return "Print all compiled methods in code cache that are alive"; 622 } 623 static const char* impact() { 624 return "Medium"; 625 } 626 static const JavaPermission permission() { 627 JavaPermission p = {"java.lang.management.ManagementPermission", 628 "monitor", NULL}; 629 return p; 630 } 631 static int num_arguments() { return 0; } 632 virtual void execute(DCmdSource source, TRAPS); 633 }; 634 635 636 class CodeCacheDCmd : public DCmd { 637 public: 638 CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} 639 static const char* name() { 640 return "Compiler.codecache"; 641 } 642 static const char* description() { 643 return "Print code cache layout and bounds."; 644 } 645 static const char* impact() { 646 return "Low"; 647 } 648 static const JavaPermission permission() { 649 JavaPermission p = {"java.lang.management.ManagementPermission", 650 "monitor", NULL}; 651 return p; 652 } 653 static int num_arguments() { return 0; } 654 virtual void execute(DCmdSource source, TRAPS); 655 }; 656 657 class CompilerDirectivesPrintDCmd : public DCmd { 658 public: 659 CompilerDirectivesPrintDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} 660 static const char* name() { 661 return "Compiler.directives_print"; 662 } 663 static const char* description() { 664 return "Print all active compiler directives."; 665 } 666 static const char* impact() { 667 return "Low"; 668 } 669 static const JavaPermission permission() { 670 JavaPermission p = {"java.lang.management.ManagementPermission", 671 "monitor", NULL}; 672 return p; 673 } 674 static int num_arguments() { return 0; } 675 virtual void execute(DCmdSource source, TRAPS); 676 }; 677 678 class CompilerDirectivesRemoveDCmd : public DCmd { 679 public: 680 CompilerDirectivesRemoveDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} 681 static const char* name() { 682 return "Compiler.directives_remove"; 683 } 684 static const char* description() { 685 return "Remove latest added compiler directive."; 686 } 687 static const char* impact() { 688 return "Low"; 689 } 690 static const JavaPermission permission() { 691 JavaPermission p = {"java.lang.management.ManagementPermission", 692 "monitor", NULL}; 693 return p; 694 } 695 static int num_arguments() { return 0; } 696 virtual void execute(DCmdSource source, TRAPS); 697 }; 698 699 class CompilerDirectivesAddDCmd : public DCmdWithParser { 700 protected: 701 DCmdArgument<char*> _filename; 702 public: 703 CompilerDirectivesAddDCmd(outputStream* output, bool heap); 704 static const char* name() { 705 return "Compiler.directives_add"; 706 } 707 static const char* description() { 708 return "Add compiler directives from file."; 709 } 710 static const char* impact() { 711 return "Low"; 712 } 713 static const JavaPermission permission() { 714 JavaPermission p = {"java.lang.management.ManagementPermission", 715 "monitor", NULL}; 716 return p; 717 } 718 static int num_arguments(); 719 virtual void execute(DCmdSource source, TRAPS); 720 }; 721 722 class CompilerDirectivesClearDCmd : public DCmd { 723 public: 724 CompilerDirectivesClearDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} 725 static const char* name() { 726 return "Compiler.directives_clear"; 727 } 728 static const char* description() { 729 return "Remove all compiler directives."; 730 } 731 static const char* impact() { 732 return "Low"; 733 } 734 static const JavaPermission permission() { 735 JavaPermission p = {"java.lang.management.ManagementPermission", 736 "monitor", NULL}; 737 return p; 738 } 739 static int num_arguments() { return 0; } 740 virtual void execute(DCmdSource source, TRAPS); 741 }; 742 743 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP