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 #include "precompiled.hpp"
  26 #include "classfile/classLoaderStats.hpp"
  27 #include "classfile/compactHashtable.hpp"
  28 #include "gc/shared/vmGCOperations.hpp"
  29 #include "oops/oop.inline.hpp"
  30 #include "runtime/javaCalls.hpp"
  31 #include "runtime/os.hpp"
  32 #include "services/diagnosticArgument.hpp"
  33 #include "services/diagnosticCommand.hpp"
  34 #include "services/diagnosticFramework.hpp"
  35 #include "services/heapDumper.hpp"
  36 #include "services/management.hpp"
  37 #include "services/writeableFlags.hpp"
  38 #include "utilities/macros.hpp"
  39 
  40 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
  41 
  42 void DCmdRegistrant::register_dcmds(){
  43   // Registration of the diagnostic commands
  44   // First argument specifies which interfaces will export the command
  45   // Second argument specifies if the command is enabled
  46   // Third  argument specifies if the command is hidden
  47   uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI
  48                          | DCmd_Source_MBean;
  49   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(full_export, true, false));
  50   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(full_export, true, false));
  51   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(full_export, true, false));
  52   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(full_export, true, false));
  53   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(full_export, true, false));
  54   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SetVMFlagDCmd>(full_export, true, false));
  55   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMDynamicLibrariesDCmd>(full_export, true, false));
  56   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export, true, false));
  57   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export, true, false));
  58   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));
  59 #if INCLUDE_SERVICES // Heap dumping/inspection supported
  60   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
  61   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
  62   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
  63   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export, true, false));
  64   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export, true, false));
  65   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export, true, false));
  66 #endif // INCLUDE_SERVICES
  67 #if INCLUDE_JVMTI
  68   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIDataDumpDCmd>(full_export, true, false));
  69 #endif // INCLUDE_JVMTI
  70   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
  71   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
  72   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
  73   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
  74   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
  75   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
  76 
  77   // Enhanced JMX Agent Support
  78   // These commands won't be exported via the DiagnosticCommandMBean until an
  79   // appropriate permission is created for them
  80   uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI;
  81   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(jmx_agent_export_flags, true,false));
  82   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(jmx_agent_export_flags, true,false));
  83   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags, true,false));
  84   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStatusDCmd>(jmx_agent_export_flags, true,false));
  85 
  86 }
  87 
  88 #ifndef HAVE_EXTRA_DCMD
  89 void DCmdRegistrant::register_dcmds_ext(){
  90    // Do nothing here
  91 }
  92 #endif
  93 
  94 
  95 HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
  96   _all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
  97   _cmd("command name", "The name of the command for which we want help",
  98         "STRING", false) {
  99   _dcmdparser.add_dcmd_option(&_all);
 100   _dcmdparser.add_dcmd_argument(&_cmd);
 101 };
 102 
 103 void HelpDCmd::execute(DCmdSource source, TRAPS) {
 104   if (_all.value()) {
 105     GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(source);
 106     for (int i = 0; i < cmd_list->length(); i++) {
 107       DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
 108                                                   strlen(cmd_list->at(i)));
 109       output()->print_cr("%s%s", factory->name(),
 110                          factory->is_enabled() ? "" : " [disabled]");
 111       output()->print_cr("\t%s", factory->description());
 112       output()->cr();
 113       factory = factory->next();
 114     }
 115   } else if (_cmd.has_value()) {
 116     DCmd* cmd = NULL;
 117     DCmdFactory* factory = DCmdFactory::factory(source, _cmd.value(),
 118                                                 strlen(_cmd.value()));
 119     if (factory != NULL) {
 120       output()->print_cr("%s%s", factory->name(),
 121                          factory->is_enabled() ? "" : " [disabled]");
 122       output()->print_cr("%s", factory->description());
 123       output()->print_cr("\nImpact: %s", factory->impact());
 124       JavaPermission p = factory->permission();
 125       if(p._class != NULL) {
 126         if(p._action != NULL) {
 127           output()->print_cr("\nPermission: %s(%s, %s)",
 128                   p._class, p._name == NULL ? "null" : p._name, p._action);
 129         } else {
 130           output()->print_cr("\nPermission: %s(%s)",
 131                   p._class, p._name == NULL ? "null" : p._name);
 132         }
 133       }
 134       output()->cr();
 135       cmd = factory->create_resource_instance(output());
 136       if (cmd != NULL) {
 137         DCmdMark mark(cmd);
 138         cmd->print_help(factory->name());
 139       }
 140     } else {
 141       output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());
 142     }
 143   } else {
 144     output()->print_cr("The following commands are available:");
 145     GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list(source);
 146     for (int i = 0; i < cmd_list->length(); i++) {
 147       DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
 148                                                   strlen(cmd_list->at(i)));
 149       output()->print_cr("%s%s", factory->name(),
 150                          factory->is_enabled() ? "" : " [disabled]");
 151       factory = factory->_next;
 152     }
 153     output()->print_cr("\nFor more information about a specific command use 'help <command>'.");
 154   }
 155 }
 156 
 157 int HelpDCmd::num_arguments() {
 158   ResourceMark rm;
 159   HelpDCmd* dcmd = new HelpDCmd(NULL, false);
 160   if (dcmd != NULL) {
 161     DCmdMark mark(dcmd);
 162     return dcmd->_dcmdparser.num_arguments();
 163   } else {
 164     return 0;
 165   }
 166 }
 167 
 168 void VersionDCmd::execute(DCmdSource source, TRAPS) {
 169   output()->print_cr("%s version %s", Abstract_VM_Version::vm_name(),
 170           Abstract_VM_Version::vm_release());
 171   JDK_Version jdk_version = JDK_Version::current();
 172   if (jdk_version.update_version() > 0) {
 173     output()->print_cr("JDK %d.%d_%02d", jdk_version.major_version(),
 174             jdk_version.minor_version(), jdk_version.update_version());
 175   } else {
 176     output()->print_cr("JDK %d.%d", jdk_version.major_version(),
 177             jdk_version.minor_version());
 178   }
 179 }
 180 
 181 PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :
 182                                    DCmdWithParser(output, heap),
 183   _all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") {
 184   _dcmdparser.add_dcmd_option(&_all);
 185 }
 186 
 187 void PrintVMFlagsDCmd::execute(DCmdSource source, TRAPS) {
 188   if (_all.value()) {
 189     CommandLineFlags::printFlags(output(), true);
 190   } else {
 191     CommandLineFlags::printSetFlags(output());
 192   }
 193 }
 194 
 195 int PrintVMFlagsDCmd::num_arguments() {
 196     ResourceMark rm;
 197     PrintVMFlagsDCmd* dcmd = new PrintVMFlagsDCmd(NULL, false);
 198     if (dcmd != NULL) {
 199       DCmdMark mark(dcmd);
 200       return dcmd->_dcmdparser.num_arguments();
 201     } else {
 202       return 0;
 203     }
 204 }
 205 
 206 SetVMFlagDCmd::SetVMFlagDCmd(outputStream* output, bool heap) :
 207                                    DCmdWithParser(output, heap),
 208   _flag("flag name", "The name of the flag we want to set",
 209         "STRING", true),
 210   _value("string value", "The value we want to set", "STRING", false) {
 211   _dcmdparser.add_dcmd_argument(&_flag);
 212   _dcmdparser.add_dcmd_argument(&_value);
 213 }
 214 
 215 void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) {
 216   const char* val = NULL;
 217   if (_value.value() != NULL) {
 218     val = _value.value();
 219   }
 220 
 221   FormatBuffer<80> err_msg("%s", "");
 222   int ret = WriteableFlags::set_flag(_flag.value(), val, Flag::MANAGEMENT, err_msg);
 223 
 224   if (ret != WriteableFlags::SUCCESS) {
 225     output()->print_cr("%s", err_msg.buffer());
 226   }
 227 }
 228 
 229 int SetVMFlagDCmd::num_arguments() {
 230   ResourceMark rm;
 231   SetVMFlagDCmd* dcmd = new SetVMFlagDCmd(NULL, false);
 232   if (dcmd != NULL) {
 233     DCmdMark mark(dcmd);
 234     return dcmd->_dcmdparser.num_arguments();
 235   } else {
 236     return 0;
 237   }
 238 }
 239 
 240 void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) {
 241   if (JvmtiExport::should_post_data_dump()) {
 242     JvmtiExport::post_data_dump();
 243   }
 244 }
 245 
 246 void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
 247   // load sun.misc.VMSupport
 248   Symbol* klass = vmSymbols::sun_misc_VMSupport();
 249   Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK);
 250   instanceKlassHandle ik (THREAD, k);
 251   if (ik->should_be_initialized()) {
 252     ik->initialize(THREAD);
 253   }
 254   if (HAS_PENDING_EXCEPTION) {
 255     java_lang_Throwable::print(PENDING_EXCEPTION, output());
 256     output()->cr();
 257     CLEAR_PENDING_EXCEPTION;
 258     return;
 259   }
 260 
 261   // invoke the serializePropertiesToByteArray method
 262   JavaValue result(T_OBJECT);
 263   JavaCallArguments args;
 264 
 265   Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();
 266   JavaCalls::call_static(&result,
 267                          ik,
 268                          vmSymbols::serializePropertiesToByteArray_name(),
 269                          signature,
 270                          &args,
 271                          THREAD);
 272   if (HAS_PENDING_EXCEPTION) {
 273     java_lang_Throwable::print(PENDING_EXCEPTION, output());
 274     output()->cr();
 275     CLEAR_PENDING_EXCEPTION;
 276     return;
 277   }
 278 
 279   // The result should be a [B
 280   oop res = (oop)result.get_jobject();
 281   assert(res->is_typeArray(), "just checking");
 282   assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
 283 
 284   // copy the bytes to the output stream
 285   typeArrayOop ba = typeArrayOop(res);
 286   jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
 287   output()->print_raw((const char*)addr, ba->length());
 288 }
 289 
 290 VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
 291                            DCmdWithParser(output, heap),
 292   _date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
 293   _dcmdparser.add_dcmd_option(&_date);
 294 }
 295 
 296 void VMUptimeDCmd::execute(DCmdSource source, TRAPS) {
 297   if (_date.value()) {
 298     output()->date_stamp(true, "", ": ");
 299   }
 300   output()->time_stamp().update_to(tty->time_stamp().ticks());
 301   output()->stamp();
 302   output()->print_cr(" s");
 303 }
 304 
 305 int VMUptimeDCmd::num_arguments() {
 306   ResourceMark rm;
 307   VMUptimeDCmd* dcmd = new VMUptimeDCmd(NULL, false);
 308   if (dcmd != NULL) {
 309     DCmdMark mark(dcmd);
 310     return dcmd->_dcmdparser.num_arguments();
 311   } else {
 312     return 0;
 313   }
 314 }
 315 
 316 void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
 317   if (!DisableExplicitGC) {
 318     Universe::heap()->collect(GCCause::_dcmd_gc_run);
 319   } else {
 320     output()->print_cr("Explicit GC is disabled, no GC has been performed.");
 321   }
 322 }
 323 
 324 void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {
 325   Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(),
 326                                                  true, CHECK);
 327   instanceKlassHandle klass(THREAD, k);
 328   JavaValue result(T_VOID);
 329   JavaCalls::call_static(&result, klass,
 330                          vmSymbols::run_finalization_name(),
 331                          vmSymbols::void_method_signature(), CHECK);
 332 }
 333 
 334 #if INCLUDE_SERVICES // Heap dumping/inspection supported
 335 HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
 336                            DCmdWithParser(output, heap),
 337   _filename("filename","Name of the dump file", "STRING",true),
 338   _all("-all", "Dump all objects, including unreachable objects",
 339        "BOOLEAN", false, "false") {
 340   _dcmdparser.add_dcmd_option(&_all);
 341   _dcmdparser.add_dcmd_argument(&_filename);
 342 }
 343 
 344 void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
 345   // Request a full GC before heap dump if _all is false
 346   // This helps reduces the amount of unreachable objects in the dump
 347   // and makes it easier to browse.
 348   HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
 349   int res = dumper.dump(_filename.value());
 350   if (res == 0) {
 351     output()->print_cr("Heap dump file created");
 352   } else {
 353     // heap dump failed
 354     ResourceMark rm;
 355     char* error = dumper.error_as_C_string();
 356     if (error == NULL) {
 357       output()->print_cr("Dump failed - reason unknown");
 358     } else {
 359       output()->print_cr("%s", error);
 360     }
 361   }
 362 }
 363 
 364 int HeapDumpDCmd::num_arguments() {
 365   ResourceMark rm;
 366   HeapDumpDCmd* dcmd = new HeapDumpDCmd(NULL, false);
 367   if (dcmd != NULL) {
 368     DCmdMark mark(dcmd);
 369     return dcmd->_dcmdparser.num_arguments();
 370   } else {
 371     return 0;
 372   }
 373 }
 374 
 375 ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
 376                                        DCmdWithParser(output, heap),
 377   _all("-all", "Inspect all objects, including unreachable objects",
 378        "BOOLEAN", false, "false") {
 379   _dcmdparser.add_dcmd_option(&_all);
 380 }
 381 
 382 void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {
 383   VM_GC_HeapInspection heapop(output(),
 384                               !_all.value() /* request full gc if false */);
 385   VMThread::execute(&heapop);
 386 }
 387 
 388 int ClassHistogramDCmd::num_arguments() {
 389   ResourceMark rm;
 390   ClassHistogramDCmd* dcmd = new ClassHistogramDCmd(NULL, false);
 391   if (dcmd != NULL) {
 392     DCmdMark mark(dcmd);
 393     return dcmd->_dcmdparser.num_arguments();
 394   } else {
 395     return 0;
 396   }
 397 }
 398 
 399 #define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total"
 400 ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) :
 401                                        DCmdWithParser(output, heap),
 402   _csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets",
 403        "BOOLEAN", false, "false"),
 404   _all("-all", "Show all columns",
 405        "BOOLEAN", false, "false"),
 406   _help("-help", "Show meaning of all the columns",
 407        "BOOLEAN", false, "false"),
 408   _columns("columns", "Comma-separated list of all the columns to show. "
 409            "If not specified, the following columns are shown: " DEFAULT_COLUMNS,
 410            "STRING", false) {
 411   _dcmdparser.add_dcmd_option(&_all);
 412   _dcmdparser.add_dcmd_option(&_csv);
 413   _dcmdparser.add_dcmd_option(&_help);
 414   _dcmdparser.add_dcmd_argument(&_columns);
 415 }
 416 
 417 void ClassStatsDCmd::execute(DCmdSource source, TRAPS) {
 418   if (!UnlockDiagnosticVMOptions) {
 419     output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions");
 420     return;
 421   }
 422 
 423   VM_GC_HeapInspection heapop(output(),
 424                               true /* request_full_gc */);
 425   heapop.set_csv_format(_csv.value());
 426   heapop.set_print_help(_help.value());
 427   heapop.set_print_class_stats(true);
 428   if (_all.value()) {
 429     if (_columns.has_value()) {
 430       output()->print_cr("Cannot specify -all and individual columns at the same time");
 431       return;
 432     } else {
 433       heapop.set_columns(NULL);
 434     }
 435   } else {
 436     if (_columns.has_value()) {
 437       heapop.set_columns(_columns.value());
 438     } else {
 439       heapop.set_columns(DEFAULT_COLUMNS);
 440     }
 441   }
 442   VMThread::execute(&heapop);
 443 }
 444 
 445 int ClassStatsDCmd::num_arguments() {
 446   ResourceMark rm;
 447   ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false);
 448   if (dcmd != NULL) {
 449     DCmdMark mark(dcmd);
 450     return dcmd->_dcmdparser.num_arguments();
 451   } else {
 452     return 0;
 453   }
 454 }
 455 #endif // INCLUDE_SERVICES
 456 
 457 ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
 458                                DCmdWithParser(output, heap),
 459   _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") {
 460   _dcmdparser.add_dcmd_option(&_locks);
 461 }
 462 
 463 void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) {
 464   // thread stacks
 465   VM_PrintThreads op1(output(), _locks.value());
 466   VMThread::execute(&op1);
 467 
 468   // JNI global handles
 469   VM_PrintJNI op2(output());
 470   VMThread::execute(&op2);
 471 
 472   // Deadlock detection
 473   VM_FindDeadlocks op3(output());
 474   VMThread::execute(&op3);
 475 }
 476 
 477 int ThreadDumpDCmd::num_arguments() {
 478   ResourceMark rm;
 479   ThreadDumpDCmd* dcmd = new ThreadDumpDCmd(NULL, false);
 480   if (dcmd != NULL) {
 481     DCmdMark mark(dcmd);
 482     return dcmd->_dcmdparser.num_arguments();
 483   } else {
 484     return 0;
 485   }
 486 }
 487 
 488 // Enhanced JMX Agent support
 489 
 490 JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :
 491 
 492   DCmdWithParser(output, heap_allocated),
 493 
 494   _config_file
 495   ("config.file",
 496    "set com.sun.management.config.file", "STRING", false),
 497 
 498   _jmxremote_port
 499   ("jmxremote.port",
 500    "set com.sun.management.jmxremote.port", "STRING", false),
 501 
 502   _jmxremote_rmi_port
 503   ("jmxremote.rmi.port",
 504    "set com.sun.management.jmxremote.rmi.port", "STRING", false),
 505 
 506   _jmxremote_ssl
 507   ("jmxremote.ssl",
 508    "set com.sun.management.jmxremote.ssl", "STRING", false),
 509 
 510   _jmxremote_registry_ssl
 511   ("jmxremote.registry.ssl",
 512    "set com.sun.management.jmxremote.registry.ssl", "STRING", false),
 513 
 514   _jmxremote_authenticate
 515   ("jmxremote.authenticate",
 516    "set com.sun.management.jmxremote.authenticate", "STRING", false),
 517 
 518   _jmxremote_password_file
 519   ("jmxremote.password.file",
 520    "set com.sun.management.jmxremote.password.file", "STRING", false),
 521 
 522   _jmxremote_access_file
 523   ("jmxremote.access.file",
 524    "set com.sun.management.jmxremote.access.file", "STRING", false),
 525 
 526   _jmxremote_login_config
 527   ("jmxremote.login.config",
 528    "set com.sun.management.jmxremote.login.config", "STRING", false),
 529 
 530   _jmxremote_ssl_enabled_cipher_suites
 531   ("jmxremote.ssl.enabled.cipher.suites",
 532    "set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),
 533 
 534   _jmxremote_ssl_enabled_protocols
 535   ("jmxremote.ssl.enabled.protocols",
 536    "set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),
 537 
 538   _jmxremote_ssl_need_client_auth
 539   ("jmxremote.ssl.need.client.auth",
 540    "set com.sun.management.jmxremote.need.client.auth", "STRING", false),
 541 
 542   _jmxremote_ssl_config_file
 543   ("jmxremote.ssl.config.file",
 544    "set com.sun.management.jmxremote.ssl_config_file", "STRING", false),
 545 
 546 // JDP Protocol support
 547   _jmxremote_autodiscovery
 548   ("jmxremote.autodiscovery",
 549    "set com.sun.management.jmxremote.autodiscovery", "STRING", false),
 550 
 551    _jdp_port
 552   ("jdp.port",
 553    "set com.sun.management.jdp.port", "INT", false),
 554 
 555    _jdp_address
 556   ("jdp.address",
 557    "set com.sun.management.jdp.address", "STRING", false),
 558 
 559    _jdp_source_addr
 560   ("jdp.source_addr",
 561    "set com.sun.management.jdp.source_addr", "STRING", false),
 562 
 563    _jdp_ttl
 564   ("jdp.ttl",
 565    "set com.sun.management.jdp.ttl", "INT", false),
 566 
 567    _jdp_pause
 568   ("jdp.pause",
 569    "set com.sun.management.jdp.pause", "INT", false),
 570 
 571    _jdp_name
 572   ("jdp.name",
 573    "set com.sun.management.jdp.name", "STRING", false)
 574 
 575   {
 576     _dcmdparser.add_dcmd_option(&_config_file);
 577     _dcmdparser.add_dcmd_option(&_jmxremote_port);
 578     _dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);
 579     _dcmdparser.add_dcmd_option(&_jmxremote_ssl);
 580     _dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);
 581     _dcmdparser.add_dcmd_option(&_jmxremote_authenticate);
 582     _dcmdparser.add_dcmd_option(&_jmxremote_password_file);
 583     _dcmdparser.add_dcmd_option(&_jmxremote_access_file);
 584     _dcmdparser.add_dcmd_option(&_jmxremote_login_config);
 585     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);
 586     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
 587     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
 588     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
 589     _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery);
 590     _dcmdparser.add_dcmd_option(&_jdp_port);
 591     _dcmdparser.add_dcmd_option(&_jdp_address);
 592     _dcmdparser.add_dcmd_option(&_jdp_source_addr);
 593     _dcmdparser.add_dcmd_option(&_jdp_ttl);
 594     _dcmdparser.add_dcmd_option(&_jdp_pause);
 595     _dcmdparser.add_dcmd_option(&_jdp_name);
 596 }
 597 
 598 
 599 int JMXStartRemoteDCmd::num_arguments() {
 600   ResourceMark rm;
 601   JMXStartRemoteDCmd* dcmd = new JMXStartRemoteDCmd(NULL, false);
 602   if (dcmd != NULL) {
 603     DCmdMark mark(dcmd);
 604     return dcmd->_dcmdparser.num_arguments();
 605   } else {
 606     return 0;
 607   }
 608 }
 609 
 610 
 611 void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
 612     ResourceMark rm(THREAD);
 613     HandleMark hm(THREAD);
 614 
 615     // Load and initialize the sun.management.Agent class
 616     // invoke startRemoteManagementAgent(string) method to start
 617     // the remote management server.
 618     // throw java.lang.NoSuchMethodError if the method doesn't exist
 619 
 620     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
 621     Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
 622     instanceKlassHandle ik (THREAD, k);
 623 
 624     JavaValue result(T_VOID);
 625 
 626     // Pass all command line arguments to java as key=value,...
 627     // All checks are done on java side
 628 
 629     int len = 0;
 630     stringStream options;
 631     char comma[2] = {0,0};
 632 
 633     // Leave default values on Agent.class side and pass only
 634     // agruments explicitly set by user. All arguments passed
 635     // to jcmd override properties with the same name set by
 636     // command line with -D or by managmenent.properties
 637     // file.
 638 #define PUT_OPTION(a) \
 639     if ( (a).is_set() ){ \
 640         options.print(\
 641                ( *((a).type()) == 'I' ) ? "%scom.sun.management.%s=%d" : "%scom.sun.management.%s=%s",\
 642                 comma, (a).name(), (a).value()); \
 643         comma[0] = ','; \
 644     }
 645 
 646     PUT_OPTION(_config_file);
 647     PUT_OPTION(_jmxremote_port);
 648     PUT_OPTION(_jmxremote_rmi_port);
 649     PUT_OPTION(_jmxremote_ssl);
 650     PUT_OPTION(_jmxremote_registry_ssl);
 651     PUT_OPTION(_jmxremote_authenticate);
 652     PUT_OPTION(_jmxremote_password_file);
 653     PUT_OPTION(_jmxremote_access_file);
 654     PUT_OPTION(_jmxremote_login_config);
 655     PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);
 656     PUT_OPTION(_jmxremote_ssl_enabled_protocols);
 657     PUT_OPTION(_jmxremote_ssl_need_client_auth);
 658     PUT_OPTION(_jmxremote_ssl_config_file);
 659     PUT_OPTION(_jmxremote_autodiscovery);
 660     PUT_OPTION(_jdp_port);
 661     PUT_OPTION(_jdp_address);
 662     PUT_OPTION(_jdp_source_addr);
 663     PUT_OPTION(_jdp_ttl);
 664     PUT_OPTION(_jdp_pause);
 665     PUT_OPTION(_jdp_name);
 666 
 667 #undef PUT_OPTION
 668 
 669     Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);
 670     JavaCalls::call_static(&result, ik, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);
 671 }
 672 
 673 JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :
 674   DCmd(output, heap_allocated) {
 675   // do nothing
 676 }
 677 
 678 void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
 679     ResourceMark rm(THREAD);
 680     HandleMark hm(THREAD);
 681 
 682     // Load and initialize the sun.management.Agent class
 683     // invoke startLocalManagementAgent(void) method to start
 684     // the local management server
 685     // throw java.lang.NoSuchMethodError if method doesn't exist
 686 
 687     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
 688     Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
 689     instanceKlassHandle ik (THREAD, k);
 690 
 691     JavaValue result(T_VOID);
 692     JavaCalls::call_static(&result, ik, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
 693 }
 694 
 695 void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {
 696     ResourceMark rm(THREAD);
 697     HandleMark hm(THREAD);
 698 
 699     // Load and initialize the sun.management.Agent class
 700     // invoke stopRemoteManagementAgent method to stop the
 701     // management server
 702     // throw java.lang.NoSuchMethodError if method doesn't exist
 703 
 704     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
 705     Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
 706     instanceKlassHandle ik (THREAD, k);
 707 
 708     JavaValue result(T_VOID);
 709     JavaCalls::call_static(&result, ik, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
 710 }
 711 
 712 JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) :
 713   DCmd(output, heap_allocated) {
 714   // do nothing
 715 }
 716 
 717 void JMXStatusDCmd::execute(DCmdSource source, TRAPS) {
 718   ResourceMark rm(THREAD);
 719   HandleMark hm(THREAD);
 720 
 721   // Load and initialize the sun.management.Agent class
 722   // invoke getManagementAgentStatus() method to generate the status info
 723   // throw java.lang.NoSuchMethodError if method doesn't exist
 724 
 725   Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
 726   Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
 727   instanceKlassHandle ik (THREAD, k);
 728 
 729   JavaValue result(T_OBJECT);
 730   JavaCalls::call_static(&result, ik, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK);
 731 
 732   jvalue* jv = (jvalue*) result.get_value_addr();
 733   oop str = (oop) jv->l;
 734   if (str != NULL) {
 735       char* out = java_lang_String::as_utf8_string(str);
 736       if (out) {
 737           output()->print_cr("%s", out);
 738           return;
 739       }
 740   }
 741   output()->print_cr("Error obtaining management agent status");
 742 }
 743 
 744 VMDynamicLibrariesDCmd::VMDynamicLibrariesDCmd(outputStream *output, bool heap_allocated) :
 745   DCmd(output, heap_allocated) {
 746   // do nothing
 747 }
 748 
 749 void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) {
 750   os::print_dll_info(output());
 751   output()->cr();
 752 }
 753 
 754 void RotateGCLogDCmd::execute(DCmdSource source, TRAPS) {
 755   if (UseGCLogFileRotation) {
 756     VM_RotateGCLog rotateop(output());
 757     VMThread::execute(&rotateop);
 758   } else {
 759     output()->print_cr("Target VM does not support GC log file rotation.");
 760   }
 761 }
 762 
 763 void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
 764   VM_PrintCompileQueue printCompileQueueOp(output());
 765   VMThread::execute(&printCompileQueueOp);
 766 }
 767 
 768 void CodeListDCmd::execute(DCmdSource source, TRAPS) {
 769   VM_PrintCodeList printCodeListOp(output());
 770   VMThread::execute(&printCodeListOp);
 771 }
 772 
 773 void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
 774   VM_PrintCodeCache printCodeCacheOp(output());
 775   VMThread::execute(&printCodeCacheOp);
 776 }
 777 
 778 #if INCLUDE_SERVICES
 779 ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
 780                                        DCmdWithParser(output, heap),
 781   _print_interfaces("-i", "Inherited interfaces should be printed.", "BOOLEAN", false, "false"),
 782   _print_subclasses("-s", "If a classname is specified, print its subclasses. "
 783                     "Otherwise only its superclasses are printed.", "BOOLEAN", false, "false"),
 784   _classname("classname", "Name of class whose hierarchy should be printed. "
 785              "If not specified, all class hierarchies are printed.",
 786              "STRING", false) {
 787   _dcmdparser.add_dcmd_option(&_print_interfaces);
 788   _dcmdparser.add_dcmd_option(&_print_subclasses);
 789   _dcmdparser.add_dcmd_argument(&_classname);
 790 }
 791 
 792 void ClassHierarchyDCmd::execute(DCmdSource source, TRAPS) {
 793   VM_PrintClassHierarchy printClassHierarchyOp(output(), _print_interfaces.value(),
 794                                                _print_subclasses.value(), _classname.value());
 795   VMThread::execute(&printClassHierarchyOp);
 796 }
 797 
 798 int ClassHierarchyDCmd::num_arguments() {
 799   ResourceMark rm;
 800   ClassHierarchyDCmd* dcmd = new ClassHierarchyDCmd(NULL, false);
 801   if (dcmd != NULL) {
 802     DCmdMark mark(dcmd);
 803     return dcmd->_dcmdparser.num_arguments();
 804   } else {
 805     return 0;
 806   }
 807 }
 808 
 809 #endif