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