1 /*
2 * Copyright (c) 2011, 2025, 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 "cds/aotMetaspace.hpp"
26 #include "cds/cds_globals.hpp"
27 #include "cds/cdsConfig.hpp"
28 #include "classfile/classLoaderDataGraph.hpp"
29 #include "classfile/classLoaderHierarchyDCmd.hpp"
30 #include "classfile/classLoaderStats.hpp"
31 #include "classfile/javaClasses.hpp"
32 #include "classfile/systemDictionary.hpp"
33 #include "classfile/vmClasses.hpp"
34 #include "code/codeCache.hpp"
35 #include "compiler/compilationMemoryStatistic.hpp"
36 #include "compiler/compileBroker.hpp"
37 #include "compiler/compiler_globals.hpp"
38 #include "compiler/directivesParser.hpp"
39 #include "gc/shared/gcVMOperations.hpp"
40 #include "jvm.h"
41 #include "memory/metaspace/metaspaceDCmd.hpp"
42 #include "memory/metaspaceUtils.hpp"
43 #include "memory/resourceArea.hpp"
44 #include "memory/universe.hpp"
45 #include "nmt/memMapPrinter.hpp"
46 #include "nmt/memTracker.hpp"
47 #include "nmt/nmtDCmd.hpp"
48 #include "oops/instanceKlass.hpp"
49 #include "oops/objArrayOop.inline.hpp"
50 #include "oops/oop.inline.hpp"
51 #include "oops/typeArrayOop.inline.hpp"
52 #include "prims/jvmtiAgentList.hpp"
53 #include "runtime/fieldDescriptor.inline.hpp"
54 #include "runtime/flags/jvmFlag.hpp"
55 #include "runtime/handles.inline.hpp"
56 #include "runtime/javaCalls.hpp"
57 #include "runtime/jniHandles.hpp"
58 #include "runtime/os.hpp"
59 #include "runtime/vm_version.hpp"
60 #include "runtime/vmOperations.hpp"
61 #include "services/diagnosticArgument.hpp"
62 #include "services/diagnosticCommand.hpp"
63 #include "services/diagnosticFramework.hpp"
64 #include "services/heapDumper.hpp"
65 #include "services/management.hpp"
66 #include "services/writeableFlags.hpp"
67 #include "utilities/debug.hpp"
68 #include "utilities/events.hpp"
69 #include "utilities/formatBuffer.hpp"
70 #include "utilities/macros.hpp"
71 #include "utilities/parseInteger.hpp"
72 #ifdef LINUX
73 #include "mallocInfoDcmd.hpp"
74 #include "os_posix.hpp"
75 #include "trimCHeapDCmd.hpp"
76
77 #include <errno.h>
78 #endif
79
80 static void loadAgentModule(TRAPS) {
81 ResourceMark rm(THREAD);
82 HandleMark hm(THREAD);
83
84 JavaValue result(T_OBJECT);
85 Handle h_module_name = java_lang_String::create_from_str("jdk.management.agent", CHECK);
86 JavaCalls::call_static(&result,
87 vmClasses::module_Modules_klass(),
88 vmSymbols::loadModule_name(),
89 vmSymbols::loadModule_signature(),
90 h_module_name,
91 THREAD);
92 }
93
94 void DCmd::register_dcmds() {
95 // Argument specifies on which interfaces a command is made available:
96 uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI
97 | DCmd_Source_MBean;
98 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(full_export));
99 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(full_export));
100 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(full_export));
101 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(full_export));
102 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSecurityPropertiesDCmd>(full_export));
103 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(full_export));
104 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SetVMFlagDCmd>(full_export));
105 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMDynamicLibrariesDCmd>(full_export));
106 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export));
107 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMInfoDCmd>(full_export));
108 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export));
109 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export));
110 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export));
111 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export));
112 #if INCLUDE_SERVICES
113 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI));
114 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export));
115 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDictionaryDCmd>(full_export));
116 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export));
117 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassesDCmd>(full_export));
118 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export));
119 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export));
120 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<metaspace::MetaspaceDCmd>(full_export));
121 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<EventLogDCmd>(full_export));
122 #if INCLUDE_JVMTI // Both JVMTI and SERVICES have to be enabled to have this dcmd
123 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIAgentLoadDCmd>(full_export));
124 #endif // INCLUDE_JVMTI
125 #endif // INCLUDE_SERVICES
126 #if INCLUDE_JVMTI
127 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIDataDumpDCmd>(full_export));
128 #endif // INCLUDE_JVMTI
129 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export));
130 #if INCLUDE_JVMTI
131 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpToFileDCmd>(full_export));
132 #endif // INCLUDE_JVMTI
133 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VThreadSchedulerDCmd>(full_export));
134 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VThreadPollersDCmd>(full_export));
135 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export));
136 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderHierarchyDCmd>(full_export));
137 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export));
138 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export));
139 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export));
140 #ifdef LINUX
141 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PerfMapDCmd>(full_export));
142 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TrimCLibcHeapDCmd>(full_export));
143 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<MallocInfoDcmd>(full_export));
144 #endif // LINUX
145 #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__)
146 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemMapDCmd>(full_export));
147 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDumpMapDCmd>(full_export));
148 #endif // LINUX or WINDOWS or MacOS
149 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeHeapAnalyticsDCmd>(full_export));
150
151 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesPrintDCmd>(full_export));
152 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesAddDCmd>(full_export));
153 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesRemoveDCmd>(full_export));
154 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesClearDCmd>(full_export));
155 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilationMemoryStatisticDCmd>(full_export));
156
157 // Enhanced JMX Agent Support
158 // These commands not currently exported via the DiagnosticCommandMBean
159 uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI;
160 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(jmx_agent_export_flags));
161 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(jmx_agent_export_flags));
162 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags));
163 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStatusDCmd>(jmx_agent_export_flags));
164
165 #if INCLUDE_CDS
166 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DumpSharedArchiveDCmd>(full_export));
167 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<AOTEndRecordingDCmd>(full_export));
168 #endif // INCLUDE_CDS
169
170 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<NMTDCmd>(full_export));
171 }
172
173 HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
174 _all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
175 _cmd("command name", "The name of the command for which we want help",
176 "STRING", false) {
177 _dcmdparser.add_dcmd_option(&_all);
178 _dcmdparser.add_dcmd_argument(&_cmd);
179 };
180
181
182 static int compare_strings(const char** s1, const char** s2) {
183 return ::strcmp(*s1, *s2);
184 }
185
186 void HelpDCmd::execute(DCmdSource source, TRAPS) {
187 if (_all.value()) {
188 GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(source);
189 cmd_list->sort(compare_strings);
190 for (int i = 0; i < cmd_list->length(); i++) {
191 DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
192 strlen(cmd_list->at(i)));
193 output()->print_cr("%s", factory->name());
194 output()->print_cr("\t%s", factory->description());
195 output()->cr();
196 factory = factory->next();
197 }
198 } else if (_cmd.has_value()) {
199 DCmd* cmd = nullptr;
200 DCmdFactory* factory = DCmdFactory::factory(source, _cmd.value(),
201 strlen(_cmd.value()));
202 if (factory != nullptr) {
203 output()->print_cr("%s", factory->name());
204 output()->print_cr("%s", factory->description());
205 output()->print_cr("\nImpact: %s", factory->impact());
206 output()->cr();
207 cmd = factory->create_resource_instance(output());
208 if (cmd != nullptr) {
209 DCmdMark mark(cmd);
210 cmd->print_help(factory->name());
211 }
212 } else {
213 output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());
214 }
215 } else {
216 output()->print_cr("The following commands are available:");
217 GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list(source);
218 cmd_list->sort(compare_strings);
219 for (int i = 0; i < cmd_list->length(); i++) {
220 DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
221 strlen(cmd_list->at(i)));
222 output()->print_cr("%s", factory->name());
223 factory = factory->_next;
224 }
225 output()->print_cr("\nFor more information about a specific command use 'help <command>'.");
226 }
227 }
228
229 void VersionDCmd::execute(DCmdSource source, TRAPS) {
230 output()->print_cr("%s version %s", VM_Version::vm_name(),
231 VM_Version::vm_release());
232 JDK_Version jdk_version = JDK_Version::current();
233 if (jdk_version.patch_version() > 0) {
234 output()->print_cr("JDK %d.%d.%d.%d", jdk_version.major_version(),
235 jdk_version.minor_version(), jdk_version.security_version(),
236 jdk_version.patch_version());
237 } else {
238 output()->print_cr("JDK %d.%d.%d", jdk_version.major_version(),
239 jdk_version.minor_version(), jdk_version.security_version());
240 }
241 }
242
243 PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :
244 DCmdWithParser(output, heap),
245 _all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") {
246 _dcmdparser.add_dcmd_option(&_all);
247 }
248
249 void PrintVMFlagsDCmd::execute(DCmdSource source, TRAPS) {
250 if (_all.value()) {
251 JVMFlag::printFlags(output(), true);
252 } else {
253 JVMFlag::printSetFlags(output());
254 }
255 }
256
257 SetVMFlagDCmd::SetVMFlagDCmd(outputStream* output, bool heap) :
258 DCmdWithParser(output, heap),
259 _flag("flag name", "The name of the flag we want to set",
260 "STRING", true),
261 _value("string value", "The value we want to set", "STRING", false) {
262 _dcmdparser.add_dcmd_argument(&_flag);
263 _dcmdparser.add_dcmd_argument(&_value);
264 }
265
266 void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) {
267 const char* val = nullptr;
268 if (_value.value() != nullptr) {
269 val = _value.value();
270 }
271
272 FormatBuffer<80> err_msg("%s", "");
273 int ret = WriteableFlags::set_flag(_flag.value(), val, JVMFlagOrigin::MANAGEMENT, err_msg);
274
275 if (ret != JVMFlag::SUCCESS) {
276 output()->print_cr("%s", err_msg.buffer());
277 }
278 }
279
280 void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) {
281 if (JvmtiExport::should_post_data_dump()) {
282 JvmtiExport::post_data_dump();
283 }
284 }
285
286 #if INCLUDE_SERVICES
287 #if INCLUDE_JVMTI
288 JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) :
289 DCmdWithParser(output, heap),
290 _libpath("library path", "Absolute path of the JVMTI agent to load.",
291 "STRING", true),
292 _option("agent option", "Option string to pass the agent.", "STRING", false) {
293 _dcmdparser.add_dcmd_argument(&_libpath);
294 _dcmdparser.add_dcmd_argument(&_option);
295 }
296
297 void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) {
298
299 if (_libpath.value() == nullptr) {
300 output()->print_cr("JVMTI.agent_load dcmd needs library path.");
301 return;
302 }
303
304 char *suffix = strrchr(_libpath.value(), '.');
305 bool is_java_agent = (suffix != nullptr) && (strncmp(".jar", suffix, 4) == 0);
306
307 if (is_java_agent) {
308 if (_option.value() == nullptr) {
309 JvmtiAgentList::load_agent("instrument", false, _libpath.value(), output());
310 } else {
311 size_t opt_len = strlen(_libpath.value()) + strlen(_option.value()) + 2;
312 if (opt_len > 4096) {
313 output()->print_cr("JVMTI agent attach failed: Options is too long.");
314 return;
315 }
316
317 char *opt = (char *)os::malloc(opt_len, mtInternal);
318 if (opt == nullptr) {
319 output()->print_cr("JVMTI agent attach failed: "
320 "Could not allocate %zu bytes for argument.",
321 opt_len);
322 return;
323 }
324
325 jio_snprintf(opt, opt_len, "%s=%s", _libpath.value(), _option.value());
326 JvmtiAgentList::load_agent("instrument", false, opt, output());
327
328 os::free(opt);
329 }
330 } else {
331 JvmtiAgentList::load_agent(_libpath.value(), true, _option.value(), output());
332 }
333 }
334
335 #endif // INCLUDE_JVMTI
336 #endif // INCLUDE_SERVICES
337
338 // helper method for printing system and security properties
339 static void print_properties(Symbol* method_name, outputStream* out, TRAPS) {
340 Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport();
341 Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK);
342 InstanceKlass* ik = InstanceKlass::cast(k);
343 if (ik->should_be_initialized()) {
344 ik->initialize(THREAD);
345 }
346 if (HAS_PENDING_EXCEPTION) {
347 java_lang_Throwable::print(PENDING_EXCEPTION, out);
348 out->cr();
349 CLEAR_PENDING_EXCEPTION;
350 return;
351 }
352 JavaValue result(T_OBJECT);
353 JavaCallArguments args;
354 Symbol* signature = vmSymbols::void_byte_array_signature();
355 JavaCalls::call_static(&result, ik, method_name, signature, &args, THREAD);
356
357 if (HAS_PENDING_EXCEPTION) {
358 java_lang_Throwable::print(PENDING_EXCEPTION, out);
359 out->cr();
360 CLEAR_PENDING_EXCEPTION;
361 return;
362 }
363 oop res = result.get_oop();
364 assert(res->is_typeArray(), "should be a byte array");
365 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "should be a byte array");
366 typeArrayOop ba = typeArrayOop(res);
367 jbyte* addr = ba->byte_at_addr(0);
368 out->print_raw((const char*)addr, ba->length());
369 }
370
371 void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
372 print_properties(vmSymbols::serializePropertiesToByteArray_name(), output(), THREAD);
373 }
374
375 void PrintSecurityPropertiesDCmd::execute(DCmdSource source, TRAPS) {
376 print_properties(vmSymbols::serializeSecurityPropertiesToByteArray_name(), output(), THREAD);
377 }
378
379 VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
380 DCmdWithParser(output, heap),
381 _date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
382 _dcmdparser.add_dcmd_option(&_date);
383 }
384
385 void VMUptimeDCmd::execute(DCmdSource source, TRAPS) {
386 if (_date.value()) {
387 output()->date_stamp(true, "", ": ");
388 }
389 output()->time_stamp().update_to(tty->time_stamp().ticks());
390 output()->stamp();
391 output()->print_cr(" s");
392 }
393
394 void VMInfoDCmd::execute(DCmdSource source, TRAPS) {
395 VMError::print_vm_info(_output);
396 }
397
398 void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
399 Universe::heap()->collect(GCCause::_dcmd_gc_run);
400 }
401
402 void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {
403 Klass* k = vmClasses::System_klass();
404 JavaValue result(T_VOID);
405 JavaCalls::call_static(&result, k,
406 vmSymbols::run_finalization_name(),
407 vmSymbols::void_method_signature(), CHECK);
408 }
409
410 void HeapInfoDCmd::execute(DCmdSource source, TRAPS) {
411 MutexLocker hl(THREAD, Heap_lock);
412 Universe::heap()->print_heap_on(output());
413 }
414
415 void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) {
416 ResourceMark rm(THREAD);
417
418 if (!InstanceKlass::is_finalization_enabled()) {
419 output()->print_cr("Finalization is disabled");
420 return;
421 }
422
423 Klass* k = SystemDictionary::resolve_or_fail(
424 vmSymbols::finalizer_histogram_klass(), true, CHECK);
425
426 JavaValue result(T_ARRAY);
427
428 // We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method
429 // and expect it to return array of FinalizerHistogramEntry as Object[]
430
431 JavaCalls::call_static(&result, k,
432 vmSymbols::get_finalizer_histogram_name(),
433 vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK);
434
435 objArrayOop result_oop = (objArrayOop) result.get_oop();
436 if (result_oop->length() == 0) {
437 output()->print_cr("No instances waiting for finalization found");
438 return;
439 }
440
441 oop foop = result_oop->obj_at(0);
442 InstanceKlass* ik = InstanceKlass::cast(foop->klass());
443
444 fieldDescriptor count_fd, name_fd;
445
446 Klass* count_res = ik->find_field(
447 vmSymbols::finalizer_histogram_entry_count_field(), vmSymbols::int_signature(), &count_fd);
448
449 Klass* name_res = ik->find_field(
450 vmSymbols::finalizer_histogram_entry_name_field(), vmSymbols::string_signature(), &name_fd);
451
452 assert(count_res != nullptr && name_res != nullptr, "Unexpected layout of FinalizerHistogramEntry");
453
454 output()->print_cr("Unreachable instances waiting for finalization");
455 output()->print_cr("#instances class name");
456 output()->print_cr("-----------------------");
457
458 for (int i = 0; i < result_oop->length(); ++i) {
459 oop element_oop = result_oop->obj_at(i);
460 oop str_oop = element_oop->obj_field(name_fd.offset());
461 char *name = java_lang_String::as_utf8_string(str_oop);
462 int count = element_oop->int_field(count_fd.offset());
463 output()->print_cr("%10d %s", count, name);
464 }
465 }
466
467 #if INCLUDE_SERVICES // Heap dumping/inspection supported
468 HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
469 DCmdWithParser(output, heap),
470 _filename("filename","Name of the dump file", "FILE",true),
471 _all("-all", "Dump all objects, including unreachable objects",
472 "BOOLEAN", false, "false"),
473 _gzip("-gz", "If specified, the heap dump is written in gzipped format "
474 "using the given compression level. 1 (recommended) is the fastest, "
475 "9 the strongest compression.", "INT", false, "1"),
476 _overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists",
477 "BOOLEAN", false, "false"),
478 _parallel("-parallel", "Number of parallel threads to use for heap dump. The VM "
479 "will try to use the specified number of threads, but might use fewer.",
480 "INT", false, "1") {
481 _dcmdparser.add_dcmd_option(&_all);
482 _dcmdparser.add_dcmd_argument(&_filename);
483 _dcmdparser.add_dcmd_option(&_gzip);
484 _dcmdparser.add_dcmd_option(&_overwrite);
485 _dcmdparser.add_dcmd_option(&_parallel);
486 }
487
488 void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
489 jlong level = -1; // -1 means no compression.
490 jlong parallel = HeapDumper::default_num_of_dump_threads();
491
492 if (_gzip.is_set()) {
493 level = _gzip.value();
494
495 if (level < 1 || level > 9) {
496 output()->print_cr("Compression level out of range (1-9): " JLONG_FORMAT, level);
497 return;
498 }
499 }
500
501 if (_parallel.is_set()) {
502 parallel = _parallel.value();
503
504 if (parallel < 0) {
505 output()->print_cr("Invalid number of parallel dump threads.");
506 return;
507 } else if (parallel == 0) {
508 // 0 implies to disable parallel heap dump, in such case, we use serial dump instead
509 parallel = 1;
510 }
511 }
512
513 // Request a full GC before heap dump if _all is false
514 // This helps reduces the amount of unreachable objects in the dump
515 // and makes it easier to browse.
516 HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
517 dumper.dump(_filename.value(), output(), (int) level, _overwrite.value(), (uint)parallel);
518 }
519
520 ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
521 DCmdWithParser(output, heap),
522 _all("-all", "Inspect all objects, including unreachable objects",
523 "BOOLEAN", false, "false"),
524 _parallel_thread_num("-parallel",
525 "Number of parallel threads to use for heap inspection. "
526 "0 (the default) means let the VM determine the number of threads to use. "
527 "1 means use one thread (disable parallelism). "
528 "For any other value the VM will try to use the specified number of "
529 "threads, but might use fewer.",
530 "INT", false, "0") {
531 _dcmdparser.add_dcmd_option(&_all);
532 _dcmdparser.add_dcmd_option(&_parallel_thread_num);
533 }
534
535 void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {
536 jlong num = _parallel_thread_num.value();
537 if (num < 0) {
538 output()->print_cr("Parallel thread number out of range (>=0): " JLONG_FORMAT, num);
539 return;
540 }
541 uint parallel_thread_num = num == 0
542 ? MAX2<uint>(1, (uint)os::initial_active_processor_count() * 3 / 8)
543 : num;
544 VM_GC_HeapInspection heapop(output(),
545 !_all.value(), /* request full gc if false */
546 parallel_thread_num);
547 VMThread::execute(&heapop);
548 }
549
550 #endif // INCLUDE_SERVICES
551
552 ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
553 DCmdWithParser(output, heap),
554 _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false"),
555 _extended("-e", "print extended thread information", "BOOLEAN", false, "false") {
556 _dcmdparser.add_dcmd_option(&_locks);
557 _dcmdparser.add_dcmd_option(&_extended);
558 }
559
560 void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) {
561 // thread stacks and JNI global handles
562 VM_PrintThreads op1(output(), _locks.value(), _extended.value(), true /* print JNI handle info */);
563 VMThread::execute(&op1);
564
565 // Deadlock detection
566 VM_FindDeadlocks op2(output());
567 VMThread::execute(&op2);
568 }
569
570 // Enhanced JMX Agent support
571
572 JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :
573
574 DCmdWithParser(output, heap_allocated),
575
576 _config_file
577 ("config.file",
578 "set com.sun.management.config.file", "STRING", false),
579
580 _jmxremote_host
581 ("jmxremote.host",
582 "set com.sun.management.jmxremote.host", "STRING", false),
583
584 _jmxremote_port
585 ("jmxremote.port",
586 "set com.sun.management.jmxremote.port", "STRING", false),
587
588 _jmxremote_rmi_port
589 ("jmxremote.rmi.port",
590 "set com.sun.management.jmxremote.rmi.port", "STRING", false),
591
592 _jmxremote_ssl
593 ("jmxremote.ssl",
594 "set com.sun.management.jmxremote.ssl", "STRING", false),
595
596 _jmxremote_registry_ssl
597 ("jmxremote.registry.ssl",
598 "set com.sun.management.jmxremote.registry.ssl", "STRING", false),
599
600 _jmxremote_authenticate
601 ("jmxremote.authenticate",
602 "set com.sun.management.jmxremote.authenticate", "STRING", false),
603
604 _jmxremote_password_file
605 ("jmxremote.password.file",
606 "set com.sun.management.jmxremote.password.file", "STRING", false),
607
608 _jmxremote_access_file
609 ("jmxremote.access.file",
610 "set com.sun.management.jmxremote.access.file", "STRING", false),
611
612 _jmxremote_login_config
613 ("jmxremote.login.config",
614 "set com.sun.management.jmxremote.login.config", "STRING", false),
615
616 _jmxremote_ssl_enabled_cipher_suites
617 ("jmxremote.ssl.enabled.cipher.suites",
618 "set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),
619
620 _jmxremote_ssl_enabled_protocols
621 ("jmxremote.ssl.enabled.protocols",
622 "set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),
623
624 _jmxremote_ssl_need_client_auth
625 ("jmxremote.ssl.need.client.auth",
626 "set com.sun.management.jmxremote.need.client.auth", "STRING", false),
627
628 _jmxremote_ssl_config_file
629 ("jmxremote.ssl.config.file",
630 "set com.sun.management.jmxremote.ssl.config.file", "STRING", false),
631
632 // JDP Protocol support
633 _jmxremote_autodiscovery
634 ("jmxremote.autodiscovery",
635 "set com.sun.management.jmxremote.autodiscovery", "STRING", false),
636
637 _jdp_port
638 ("jdp.port",
639 "set com.sun.management.jdp.port", "INT", false),
640
641 _jdp_address
642 ("jdp.address",
643 "set com.sun.management.jdp.address", "STRING", false),
644
645 _jdp_source_addr
646 ("jdp.source_addr",
647 "set com.sun.management.jdp.source_addr", "STRING", false),
648
649 _jdp_ttl
650 ("jdp.ttl",
651 "set com.sun.management.jdp.ttl", "INT", false),
652
653 _jdp_pause
654 ("jdp.pause",
655 "set com.sun.management.jdp.pause", "INT", false),
656
657 _jdp_name
658 ("jdp.name",
659 "set com.sun.management.jdp.name", "STRING", false)
660
661 {
662 _dcmdparser.add_dcmd_option(&_config_file);
663 _dcmdparser.add_dcmd_option(&_jmxremote_host);
664 _dcmdparser.add_dcmd_option(&_jmxremote_port);
665 _dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);
666 _dcmdparser.add_dcmd_option(&_jmxremote_ssl);
667 _dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);
668 _dcmdparser.add_dcmd_option(&_jmxremote_authenticate);
669 _dcmdparser.add_dcmd_option(&_jmxremote_password_file);
670 _dcmdparser.add_dcmd_option(&_jmxremote_access_file);
671 _dcmdparser.add_dcmd_option(&_jmxremote_login_config);
672 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);
673 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
674 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
675 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
676 _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery);
677 _dcmdparser.add_dcmd_option(&_jdp_port);
678 _dcmdparser.add_dcmd_option(&_jdp_address);
679 _dcmdparser.add_dcmd_option(&_jdp_source_addr);
680 _dcmdparser.add_dcmd_option(&_jdp_ttl);
681 _dcmdparser.add_dcmd_option(&_jdp_pause);
682 _dcmdparser.add_dcmd_option(&_jdp_name);
683 }
684
685 void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
686 ResourceMark rm(THREAD);
687 HandleMark hm(THREAD);
688
689 // Load and initialize the jdk.internal.agent.Agent class
690 // invoke startRemoteManagementAgent(string) method to start
691 // the remote management server.
692 // throw java.lang.NoSuchMethodError if the method doesn't exist
693
694 loadAgentModule(CHECK);
695 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
696 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
697
698 JavaValue result(T_VOID);
699
700 // Pass all command line arguments to java as key=value,...
701 // All checks are done on java side
702
703 int len = 0;
704 stringStream options;
705 char comma[2] = {0,0};
706
707 // Leave default values on Agent.class side and pass only
708 // arguments explicitly set by user. All arguments passed
709 // to jcmd override properties with the same name set by
710 // command line with -D or by managmenent.properties
711 // file.
712 #define PUT_OPTION(a) \
713 do { \
714 if ( (a).is_set() ){ \
715 if ( *((a).type()) == 'I' ) { \
716 options.print("%scom.sun.management.%s=" JLONG_FORMAT, comma, (a).name(), (jlong)((a).value())); \
717 } else { \
718 options.print("%scom.sun.management.%s=%s", comma, (a).name(), (char*)((a).value())); \
719 } \
720 comma[0] = ','; \
721 }\
722 } while(0);
723
724
725 PUT_OPTION(_config_file);
726 PUT_OPTION(_jmxremote_host);
727 PUT_OPTION(_jmxremote_port);
728 PUT_OPTION(_jmxremote_rmi_port);
729 PUT_OPTION(_jmxremote_ssl);
730 PUT_OPTION(_jmxremote_registry_ssl);
731 PUT_OPTION(_jmxremote_authenticate);
732 PUT_OPTION(_jmxremote_password_file);
733 PUT_OPTION(_jmxremote_access_file);
734 PUT_OPTION(_jmxremote_login_config);
735 PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);
736 PUT_OPTION(_jmxremote_ssl_enabled_protocols);
737 PUT_OPTION(_jmxremote_ssl_need_client_auth);
738 PUT_OPTION(_jmxremote_ssl_config_file);
739 PUT_OPTION(_jmxremote_autodiscovery);
740 PUT_OPTION(_jdp_port);
741 PUT_OPTION(_jdp_address);
742 PUT_OPTION(_jdp_source_addr);
743 PUT_OPTION(_jdp_ttl);
744 PUT_OPTION(_jdp_pause);
745 PUT_OPTION(_jdp_name);
746
747 #undef PUT_OPTION
748
749 Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);
750 JavaCalls::call_static(&result, k, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);
751 }
752
753 JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :
754 DCmd(output, heap_allocated) {
755 // do nothing
756 }
757
758 void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
759 ResourceMark rm(THREAD);
760 HandleMark hm(THREAD);
761
762 // Load and initialize the jdk.internal.agent.Agent class
763 // invoke startLocalManagementAgent(void) method to start
764 // the local management server
765 // throw java.lang.NoSuchMethodError if method doesn't exist
766
767 loadAgentModule(CHECK);
768 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
769 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
770
771 JavaValue result(T_VOID);
772 JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
773 }
774
775 void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {
776 ResourceMark rm(THREAD);
777 HandleMark hm(THREAD);
778
779 // Load and initialize the jdk.internal.agent.Agent class
780 // invoke stopRemoteManagementAgent method to stop the
781 // management server
782 // throw java.lang.NoSuchMethodError if method doesn't exist
783
784 loadAgentModule(CHECK);
785 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
786 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
787
788 JavaValue result(T_VOID);
789 JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
790 }
791
792 JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) :
793 DCmd(output, heap_allocated) {
794 // do nothing
795 }
796
797 void JMXStatusDCmd::execute(DCmdSource source, TRAPS) {
798 ResourceMark rm(THREAD);
799 HandleMark hm(THREAD);
800
801 // Load and initialize the jdk.internal.agent.Agent class
802 // invoke getManagementAgentStatus() method to generate the status info
803 // throw java.lang.NoSuchMethodError if method doesn't exist
804
805 loadAgentModule(CHECK);
806 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
807 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
808
809 JavaValue result(T_OBJECT);
810 JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK);
811
812 jvalue* jv = (jvalue*) result.get_value_addr();
813 oop str = cast_to_oop(jv->l);
814 if (str != nullptr) {
815 char* out = java_lang_String::as_utf8_string(str);
816 if (out) {
817 // Avoid using print_cr() because length maybe longer than O_BUFLEN
818 output()->print_raw_cr(out);
819 return;
820 }
821 }
822 output()->print_cr("Error obtaining management agent status");
823 }
824
825 VMDynamicLibrariesDCmd::VMDynamicLibrariesDCmd(outputStream *output, bool heap_allocated) :
826 DCmd(output, heap_allocated) {
827 // do nothing
828 }
829
830 void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) {
831 os::print_dll_info(output());
832 output()->cr();
833 }
834
835 void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
836 VM_PrintCompileQueue printCompileQueueOp(output());
837 VMThread::execute(&printCompileQueueOp);
838 }
839
840 void CodeListDCmd::execute(DCmdSource source, TRAPS) {
841 CodeCache::print_codelist(output());
842 }
843
844 void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
845 CodeCache::print_layout(output());
846 }
847
848 #ifdef LINUX
849 PerfMapDCmd::PerfMapDCmd(outputStream* output, bool heap) :
850 DCmdWithParser(output, heap),
851 _filename("filename", "Name of the map file", "FILE", false, DEFAULT_PERFMAP_FILENAME)
852 {
853 _dcmdparser.add_dcmd_argument(&_filename);
854 }
855
856 void PerfMapDCmd::execute(DCmdSource source, TRAPS) {
857 CodeCache::write_perf_map(_filename.value(), output());
858 }
859 #endif // LINUX
860
861 //---< BEGIN >--- CodeHeap State Analytics.
862 CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) :
863 DCmdWithParser(output, heap),
864 _function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard", "STRING", false, "all"),
865 _granularity("granularity", "Detail level - smaller value -> more detail", "INT", false, "4096") {
866 _dcmdparser.add_dcmd_argument(&_function);
867 _dcmdparser.add_dcmd_argument(&_granularity);
868 }
869
870 void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) {
871 jlong granularity = _granularity.value();
872 if (granularity < 1) {
873 Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
874 "Invalid granularity value " JLONG_FORMAT ". Should be positive.\n", granularity);
875 return;
876 }
877
878 CompileBroker::print_heapinfo(output(), _function.value(), granularity);
879 }
880 //---< END >--- CodeHeap State Analytics.
881
882 EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) :
883 DCmdWithParser(output, heap),
884 _log("log", "Name of log to be printed. If omitted, all logs are printed.", "STRING", false, nullptr),
885 _max("max", "Maximum number of events to be printed (newest first). If omitted or zero, all events are printed.", "INT", false, "0")
886 {
887 _dcmdparser.add_dcmd_option(&_log);
888 _dcmdparser.add_dcmd_option(&_max);
889 }
890
891 void EventLogDCmd::execute(DCmdSource source, TRAPS) {
892 int max = (int)_max.value();
893 if (max < 0) {
894 output()->print_cr("Invalid max option: \"%d\".", max);
895 return;
896 }
897 const char* log_name = _log.value();
898 if (log_name != nullptr) {
899 Events::print_one(output(), log_name, max);
900 } else {
901 Events::print_all(output(), max);
902 }
903 }
904
905 void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {
906 DirectivesStack::print(output());
907 }
908
909 CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :
910 DCmdWithParser(output, heap),
911 _filename("filename","Name of the directives file", "STRING",true) {
912 _dcmdparser.add_dcmd_argument(&_filename);
913 }
914
915 void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {
916 DirectivesParser::parse_from_file(_filename.value(), output(), true);
917 }
918
919 void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
920 DirectivesStack::pop(1);
921 }
922
923 void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
924 DirectivesStack::clear();
925 }
926 #if INCLUDE_SERVICES
927 ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
928 DCmdWithParser(output, heap),
929 _print_interfaces("-i", "Inherited interfaces should be printed.", "BOOLEAN", false, "false"),
930 _print_subclasses("-s", "If a classname is specified, print its subclasses "
931 "in addition to its superclasses. Without this option only the "
932 "superclasses will be printed.", "BOOLEAN", false, "false"),
933 _classname("classname", "Name of class whose hierarchy should be printed. "
934 "If not specified, all class hierarchies are printed.",
935 "STRING", false) {
936 _dcmdparser.add_dcmd_option(&_print_interfaces);
937 _dcmdparser.add_dcmd_option(&_print_subclasses);
938 _dcmdparser.add_dcmd_argument(&_classname);
939 }
940
941 void ClassHierarchyDCmd::execute(DCmdSource source, TRAPS) {
942 VM_PrintClassHierarchy printClassHierarchyOp(output(), _print_interfaces.value(),
943 _print_subclasses.value(), _classname.value());
944 VMThread::execute(&printClassHierarchyOp);
945 }
946 #endif
947
948 ClassesDCmd::ClassesDCmd(outputStream* output, bool heap) :
949 DCmdWithParser(output, heap),
950 _verbose("-verbose",
951 "Dump the detailed content of a Java class. "
952 "Some classes are annotated with flags: "
953 "F = has, or inherits, a non-empty finalize method, "
954 "f = has final method, "
955 "W = methods rewritten, "
956 "C = marked with @Contended annotation, "
957 "R = has been redefined, "
958 "S = is shared class",
959 "BOOLEAN", false, "false") {
960 _dcmdparser.add_dcmd_option(&_verbose);
961 }
962
963 class VM_PrintClasses : public VM_Operation {
964 private:
965 outputStream* _out;
966 bool _verbose;
967 public:
968 VM_PrintClasses(outputStream* out, bool verbose) : _out(out), _verbose(verbose) {}
969
970 virtual VMOp_Type type() const { return VMOp_PrintClasses; }
971
972 virtual void doit() {
973 PrintClassClosure closure(_out, _verbose);
974 ClassLoaderDataGraph::classes_do(&closure);
975 }
976 };
977
978 void ClassesDCmd::execute(DCmdSource source, TRAPS) {
979 VM_PrintClasses vmop(output(), _verbose.value());
980 VMThread::execute(&vmop);
981 }
982
983 #if INCLUDE_CDS
984 void AOTEndRecordingDCmd::execute(DCmdSource source, TRAPS) {
985 if (!CDSConfig::is_dumping_preimage_static_archive()) {
986 output()->print_cr("AOT.end_recording is unsupported when VM flags -XX:AOTMode=record or -XX:AOTCacheOutput=<file> are missing.");
987 return;
988 }
989
990 if (AOTMetaspace::preimage_static_archive_dumped()) {
991 output()->print_cr("Recording has already ended.");
992 return;
993 }
994
995 AOTMetaspace::dump_static_archive(THREAD);
996 if (!AOTMetaspace::preimage_static_archive_dumped()) {
997 output()->print_cr("Error: Failed to end recording.");
998 return;
999 }
1000
1001 output()->print_cr("Recording ended successfully.");
1002 }
1003 #endif // INCLUDE_CDS
1004
1005 #if INCLUDE_CDS
1006 #define DEFAULT_CDS_ARCHIVE_FILENAME "java_pid%p_<subcmd>.jsa"
1007
1008 DumpSharedArchiveDCmd::DumpSharedArchiveDCmd(outputStream* output, bool heap) :
1009 DCmdWithParser(output, heap),
1010 _suboption("subcmd", "static_dump | dynamic_dump", "STRING", true),
1011 _filename("filename", "Name of shared archive to be dumped", "FILE", false,
1012 DEFAULT_CDS_ARCHIVE_FILENAME)
1013 {
1014 _dcmdparser.add_dcmd_argument(&_suboption);
1015 _dcmdparser.add_dcmd_argument(&_filename);
1016 }
1017
1018 void DumpSharedArchiveDCmd::execute(DCmdSource source, TRAPS) {
1019 jboolean is_static;
1020 const char* scmd = _suboption.value();
1021
1022 // The check for _filename.is_set() is because we don't want to use
1023 // DEFAULT_CDS_ARCHIVE_FILENAME, since it is meant as a description
1024 // of the default, not the actual default.
1025 const char* file = _filename.is_set() ? _filename.value() : nullptr;
1026
1027 if (strcmp(scmd, "static_dump") == 0) {
1028 is_static = JNI_TRUE;
1029 output()->print("Static dump: ");
1030 } else if (strcmp(scmd, "dynamic_dump") == 0) {
1031 is_static = JNI_FALSE;
1032 output()->print("Dynamic dump: ");
1033 if (!CDSConfig::is_using_archive()) {
1034 output()->print_cr("Dynamic dump is unsupported when base CDS archive is not loaded");
1035 return;
1036 }
1037 if (!RecordDynamicDumpInfo) {
1038 output()->print_cr("Dump dynamic should run with -XX:+RecordDynamicDumpInfo");
1039 return;
1040 }
1041 } else {
1042 output()->print_cr("Invalid command for VM.cds, valid input is static_dump or dynamic_dump");
1043 return;
1044 }
1045
1046 // call CDS.dumpSharedArchive
1047 Handle fileh;
1048 if (file != nullptr) {
1049 fileh = java_lang_String::create_from_str(file, CHECK);
1050 }
1051 Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
1052 Klass* cds_klass = SystemDictionary::resolve_or_fail(cds_name, true /*throw error*/, CHECK);
1053 JavaValue result(T_OBJECT);
1054 JavaCallArguments args;
1055 args.push_int(is_static);
1056 args.push_oop(fileh);
1057 JavaCalls::call_static(&result,
1058 cds_klass,
1059 vmSymbols::dumpSharedArchive(),
1060 vmSymbols::dumpSharedArchive_signature(),
1061 &args, CHECK);
1062 if (!HAS_PENDING_EXCEPTION) {
1063 assert(result.get_type() == T_OBJECT, "Sanity check");
1064 // result contains the archive name
1065 char* archive_name = java_lang_String::as_utf8_string(result.get_oop());
1066 output()->print_cr("%s", archive_name);
1067 }
1068 }
1069 #endif // INCLUDE_CDS
1070
1071 ThreadDumpToFileDCmd::ThreadDumpToFileDCmd(outputStream* output, bool heap) :
1072 DCmdWithParser(output, heap),
1073 _overwrite("-overwrite", "May overwrite existing file", "BOOLEAN", false, "false"),
1074 _format("-format", "Output format (\"plain\" or \"json\")", "STRING", false, "plain"),
1075 _filepath("filepath", "The file path to the output file", "FILE", true) {
1076 _dcmdparser.add_dcmd_option(&_overwrite);
1077 _dcmdparser.add_dcmd_option(&_format);
1078 _dcmdparser.add_dcmd_argument(&_filepath);
1079 }
1080
1081 void ThreadDumpToFileDCmd::execute(DCmdSource source, TRAPS) {
1082 bool json = (_format.value() != nullptr) && (strcmp(_format.value(), "json") == 0);
1083 char* path = _filepath.value();
1084 bool overwrite = _overwrite.value();
1085 Symbol* name = (json) ? vmSymbols::dumpThreadsToJson_name() : vmSymbols::dumpThreads_name();
1086 dumpToFile(name, vmSymbols::string_bool_byte_array_signature(), path, overwrite, CHECK);
1087 }
1088
1089 void ThreadDumpToFileDCmd::dumpToFile(Symbol* name, Symbol* signature, const char* path, bool overwrite, TRAPS) {
1090 ResourceMark rm(THREAD);
1091 HandleMark hm(THREAD);
1092
1093 Handle h_path = java_lang_String::create_from_str(path, CHECK);
1094
1095 Symbol* sym = vmSymbols::jdk_internal_vm_ThreadDumper();
1096 Klass* k = SystemDictionary::resolve_or_fail(sym, true, CHECK);
1097
1098 // invoke the ThreadDump method to dump to file
1099 JavaValue result(T_OBJECT);
1100 JavaCallArguments args;
1101 args.push_oop(h_path);
1102 args.push_int(overwrite ? JNI_TRUE : JNI_FALSE);
1103 JavaCalls::call_static(&result,
1104 k,
1105 name,
1106 signature,
1107 &args,
1108 THREAD);
1109 if (HAS_PENDING_EXCEPTION) {
1110 java_lang_Throwable::print(PENDING_EXCEPTION, output());
1111 output()->cr();
1112 CLEAR_PENDING_EXCEPTION;
1113 return;
1114 }
1115
1116 // check that result is byte array
1117 oop res = cast_to_oop(result.get_jobject());
1118 assert(res->is_typeArray(), "just checking");
1119 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
1120
1121 // copy the bytes to the output stream
1122 typeArrayOop ba = typeArrayOop(res);
1123 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
1124 output()->print_raw((const char*)addr, ba->length());
1125 }
1126
1127 // Calls a static no-arg method on jdk.internal.vm.JcmdVThreadCommands that returns a byte[] with
1128 // the output. If the method completes successfully then the bytes are copied to the output stream.
1129 // If the method fails then the exception is printed to the output stream.
1130 static void execute_vthread_command(Symbol* method_name, outputStream* output, TRAPS) {
1131 ResourceMark rm(THREAD);
1132 HandleMark hm(THREAD);
1133
1134 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_JcmdVThreadCommands(), true, CHECK);
1135
1136 JavaValue result(T_OBJECT);
1137 JavaCallArguments args;
1138 JavaCalls::call_static(&result,
1139 k,
1140 method_name,
1141 vmSymbols::void_byte_array_signature(),
1142 &args,
1143 THREAD);
1144 if (HAS_PENDING_EXCEPTION) {
1145 java_lang_Throwable::print(PENDING_EXCEPTION, output);
1146 output->cr();
1147 CLEAR_PENDING_EXCEPTION;
1148 return;
1149 }
1150
1151 // copy the bytes to the output stream
1152 oop res = cast_to_oop(result.get_jobject());
1153 typeArrayOop ba = typeArrayOop(res);
1154 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
1155 output->print_raw((const char*)addr, ba->length());
1156 }
1157
1158 void VThreadSchedulerDCmd::execute(DCmdSource source, TRAPS) {
1159 execute_vthread_command(vmSymbols::printScheduler_name(), output(), CHECK);
1160 }
1161
1162 void VThreadPollersDCmd::execute(DCmdSource source, TRAPS) {
1163 execute_vthread_command(vmSymbols::printPollers_name(), output(), CHECK);
1164 }
1165
1166 CompilationMemoryStatisticDCmd::CompilationMemoryStatisticDCmd(outputStream* output, bool heap) :
1167 DCmdWithParser(output, heap),
1168 _verbose("verbose", "Print detailed information", "BOOLEAN", false, "false"),
1169 _legend("legend", "Table mode: print legend", "BOOLEAN", false, "false"),
1170 _minsize("minsize", "Minimum memory size", "MEMORY SIZE", false, "0") {
1171 _dcmdparser.add_dcmd_option(&_verbose);
1172 _dcmdparser.add_dcmd_option(&_minsize);
1173 _dcmdparser.add_dcmd_option(&_legend);
1174 }
1175
1176 void CompilationMemoryStatisticDCmd::execute(DCmdSource source, TRAPS) {
1177 const size_t minsize = _minsize.has_value() ? _minsize.value()._size : 0;
1178 CompilationMemoryStatistic::print_jcmd_report(output(), _verbose.value(), _legend.value(), minsize);
1179 }
1180
1181 #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__)
1182
1183 SystemMapDCmd::SystemMapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
1184
1185 void SystemMapDCmd::execute(DCmdSource source, TRAPS) {
1186 MemMapPrinter::print_all_mappings(output());
1187 }
1188
1189 static constexpr char default_filename[] = "vm_memory_map_%p.txt";
1190
1191 SystemDumpMapDCmd::SystemDumpMapDCmd(outputStream* output, bool heap) :
1192 DCmdWithParser(output, heap),
1193 _filename("-F", "file path", "FILE", false, default_filename) {
1194 _dcmdparser.add_dcmd_option(&_filename);
1195 }
1196
1197 void SystemDumpMapDCmd::execute(DCmdSource source, TRAPS) {
1198 const char* name = _filename.value();
1199 if (name == nullptr || name[0] == 0) {
1200 output()->print_cr("filename is empty or not specified. No file written");
1201 return;
1202 }
1203 fileStream fs(name);
1204 if (fs.is_open()) {
1205 if (!MemTracker::enabled()) {
1206 output()->print_cr("(NMT is disabled, will not annotate mappings).");
1207 }
1208 MemMapPrinter::print_all_mappings(&fs);
1209 // For the readers convenience, resolve path name.
1210 char tmp[JVM_MAXPATHLEN];
1211 const char* absname = os::realpath(name, tmp, sizeof(tmp));
1212 name = absname != nullptr ? absname : name;
1213 output()->print_cr("Memory map dumped to \"%s\".", name);
1214 } else {
1215 output()->print_cr("Failed to open \"%s\" for writing (%s).", name, os::strerror(errno));
1216 }
1217 }
1218
1219 #endif // LINUX