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