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