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