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<PrintVMFlagsDCmd>(full_export));
103 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SetVMFlagDCmd>(full_export));
104 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMDynamicLibrariesDCmd>(full_export));
105 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export));
106 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMInfoDCmd>(full_export));
107 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export));
108 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export));
109 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export));
110 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export));
111 #if INCLUDE_SERVICES
112 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI));
113 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export));
114 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDictionaryDCmd>(full_export));
115 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export));
116 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassesDCmd>(full_export));
117 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export));
118 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export));
119 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<metaspace::MetaspaceDCmd>(full_export));
120 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintClassLayoutDCmd>(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 void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
339 // load VMSupport
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, output());
348 output()->cr();
349 CLEAR_PENDING_EXCEPTION;
350 return;
351 }
352
353 // invoke the serializePropertiesToByteArray method
354 JavaValue result(T_OBJECT);
355 JavaCallArguments args;
356
357 Symbol* signature = vmSymbols::void_byte_array_signature();
358 JavaCalls::call_static(&result,
359 ik,
360 vmSymbols::serializePropertiesToByteArray_name(),
361 signature,
362 &args,
363 THREAD);
364 if (HAS_PENDING_EXCEPTION) {
365 java_lang_Throwable::print(PENDING_EXCEPTION, output());
366 output()->cr();
367 CLEAR_PENDING_EXCEPTION;
368 return;
369 }
370
371 // The result should be a [B
372 oop res = result.get_oop();
373 assert(res->is_typeArray(), "just checking");
374 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
375
376 // copy the bytes to the output stream
377 typeArrayOop ba = typeArrayOop(res);
378 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
379 output()->print_raw((const char*)addr, ba->length());
380 }
381
382 VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
383 DCmdWithParser(output, heap),
384 _date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
385 _dcmdparser.add_dcmd_option(&_date);
386 }
387
388 void VMUptimeDCmd::execute(DCmdSource source, TRAPS) {
389 if (_date.value()) {
390 output()->date_stamp(true, "", ": ");
391 }
392 output()->time_stamp().update_to(tty->time_stamp().ticks());
393 output()->stamp();
394 output()->print_cr(" s");
395 }
396
397 void VMInfoDCmd::execute(DCmdSource source, TRAPS) {
398 VMError::print_vm_info(_output);
399 }
400
401 void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
402 Universe::heap()->collect(GCCause::_dcmd_gc_run);
403 }
404
405 void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {
406 Klass* k = vmClasses::System_klass();
407 JavaValue result(T_VOID);
408 JavaCalls::call_static(&result, k,
409 vmSymbols::run_finalization_name(),
410 vmSymbols::void_method_signature(), CHECK);
411 }
412
413 void HeapInfoDCmd::execute(DCmdSource source, TRAPS) {
414 MutexLocker hl(THREAD, Heap_lock);
415 Universe::heap()->print_heap_on(output());
416 }
417
418 void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) {
419 ResourceMark rm(THREAD);
420
421 if (!InstanceKlass::is_finalization_enabled()) {
422 output()->print_cr("Finalization is disabled");
423 return;
424 }
425
426 Klass* k = SystemDictionary::resolve_or_fail(
427 vmSymbols::finalizer_histogram_klass(), true, CHECK);
428
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, k,
435 vmSymbols::get_finalizer_histogram_name(),
436 vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK);
437
438 objArrayOop result_oop = (objArrayOop) result.get_oop();
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 != nullptr && name_res != nullptr, "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
471 HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
472 DCmdWithParser(output, heap),
473 _filename("filename","Name of the dump file", "FILE",true),
474 _all("-all", "Dump all objects, including unreachable objects",
475 "BOOLEAN", false, "false"),
476 _gzip("-gz", "If specified, the heap dump is written in gzipped format "
477 "using the given compression level. 1 (recommended) is the fastest, "
478 "9 the strongest compression.", "INT", false, "1"),
479 _overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists",
480 "BOOLEAN", false, "false"),
481 _parallel("-parallel", "Number of parallel threads to use for heap dump. The VM "
482 "will try to use the specified number of threads, but might use fewer.",
483 "INT", false, "1") {
484 _dcmdparser.add_dcmd_option(&_all);
485 _dcmdparser.add_dcmd_argument(&_filename);
486 _dcmdparser.add_dcmd_option(&_gzip);
487 _dcmdparser.add_dcmd_option(&_overwrite);
488 _dcmdparser.add_dcmd_option(&_parallel);
489 }
490
491 void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
492 jlong level = -1; // -1 means no compression.
493 jlong parallel = HeapDumper::default_num_of_dump_threads();
494
495 if (_gzip.is_set()) {
496 level = _gzip.value();
497
498 if (level < 1 || level > 9) {
499 output()->print_cr("Compression level out of range (1-9): " JLONG_FORMAT, level);
500 return;
501 }
502 }
503
504 if (_parallel.is_set()) {
505 parallel = _parallel.value();
506
507 if (parallel < 0) {
508 output()->print_cr("Invalid number of parallel dump threads.");
509 return;
510 } else if (parallel == 0) {
511 // 0 implies to disable parallel heap dump, in such case, we use serial dump instead
512 parallel = 1;
513 }
514 }
515
516 // Request a full GC before heap dump if _all is false
517 // This helps reduces the amount of unreachable objects in the dump
518 // and makes it easier to browse.
519 HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
520 dumper.dump(_filename.value(), output(), (int) level, _overwrite.value(), (uint)parallel);
521 }
522
523 ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
524 DCmdWithParser(output, heap),
525 _all("-all", "Inspect all objects, including unreachable objects",
526 "BOOLEAN", false, "false"),
527 _parallel_thread_num("-parallel",
528 "Number of parallel threads to use for heap inspection. "
529 "0 (the default) means let the VM determine the number of threads to use. "
530 "1 means use one thread (disable parallelism). "
531 "For any other value the VM will try to use the specified number of "
532 "threads, but might use fewer.",
533 "INT", false, "0") {
534 _dcmdparser.add_dcmd_option(&_all);
535 _dcmdparser.add_dcmd_option(&_parallel_thread_num);
536 }
537
538 void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {
539 jlong num = _parallel_thread_num.value();
540 if (num < 0) {
541 output()->print_cr("Parallel thread number out of range (>=0): " JLONG_FORMAT, num);
542 return;
543 }
544 uint parallel_thread_num = num == 0
545 ? MAX2<uint>(1, (uint)os::initial_active_processor_count() * 3 / 8)
546 : num;
547 VM_GC_HeapInspection heapop(output(),
548 !_all.value(), /* request full gc if false */
549 parallel_thread_num);
550 VMThread::execute(&heapop);
551 }
552
553 #endif // INCLUDE_SERVICES
554
555 ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
556 DCmdWithParser(output, heap),
557 _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false"),
558 _extended("-e", "print extended thread information", "BOOLEAN", false, "false") {
559 _dcmdparser.add_dcmd_option(&_locks);
560 _dcmdparser.add_dcmd_option(&_extended);
561 }
562
563 void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) {
564 // thread stacks and JNI global handles
565 VM_PrintThreads op1(output(), _locks.value(), _extended.value(), true /* print JNI handle info */);
566 VMThread::execute(&op1);
567
568 // Deadlock detection
569 VM_FindDeadlocks op2(output());
570 VMThread::execute(&op2);
571 }
572
573 // Enhanced JMX Agent support
574
575 JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :
576
577 DCmdWithParser(output, heap_allocated),
578
579 _config_file
580 ("config.file",
581 "set com.sun.management.config.file", "STRING", false),
582
583 _jmxremote_host
584 ("jmxremote.host",
585 "set com.sun.management.jmxremote.host", "STRING", false),
586
587 _jmxremote_port
588 ("jmxremote.port",
589 "set com.sun.management.jmxremote.port", "STRING", false),
590
591 _jmxremote_rmi_port
592 ("jmxremote.rmi.port",
593 "set com.sun.management.jmxremote.rmi.port", "STRING", false),
594
595 _jmxremote_ssl
596 ("jmxremote.ssl",
597 "set com.sun.management.jmxremote.ssl", "STRING", false),
598
599 _jmxremote_registry_ssl
600 ("jmxremote.registry.ssl",
601 "set com.sun.management.jmxremote.registry.ssl", "STRING", false),
602
603 _jmxremote_authenticate
604 ("jmxremote.authenticate",
605 "set com.sun.management.jmxremote.authenticate", "STRING", false),
606
607 _jmxremote_password_file
608 ("jmxremote.password.file",
609 "set com.sun.management.jmxremote.password.file", "STRING", false),
610
611 _jmxremote_access_file
612 ("jmxremote.access.file",
613 "set com.sun.management.jmxremote.access.file", "STRING", false),
614
615 _jmxremote_login_config
616 ("jmxremote.login.config",
617 "set com.sun.management.jmxremote.login.config", "STRING", false),
618
619 _jmxremote_ssl_enabled_cipher_suites
620 ("jmxremote.ssl.enabled.cipher.suites",
621 "set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),
622
623 _jmxremote_ssl_enabled_protocols
624 ("jmxremote.ssl.enabled.protocols",
625 "set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),
626
627 _jmxremote_ssl_need_client_auth
628 ("jmxremote.ssl.need.client.auth",
629 "set com.sun.management.jmxremote.need.client.auth", "STRING", false),
630
631 _jmxremote_ssl_config_file
632 ("jmxremote.ssl.config.file",
633 "set com.sun.management.jmxremote.ssl.config.file", "STRING", false),
634
635 // JDP Protocol support
636 _jmxremote_autodiscovery
637 ("jmxremote.autodiscovery",
638 "set com.sun.management.jmxremote.autodiscovery", "STRING", false),
639
640 _jdp_port
641 ("jdp.port",
642 "set com.sun.management.jdp.port", "INT", false),
643
644 _jdp_address
645 ("jdp.address",
646 "set com.sun.management.jdp.address", "STRING", false),
647
648 _jdp_source_addr
649 ("jdp.source_addr",
650 "set com.sun.management.jdp.source_addr", "STRING", false),
651
652 _jdp_ttl
653 ("jdp.ttl",
654 "set com.sun.management.jdp.ttl", "INT", false),
655
656 _jdp_pause
657 ("jdp.pause",
658 "set com.sun.management.jdp.pause", "INT", false),
659
660 _jdp_name
661 ("jdp.name",
662 "set com.sun.management.jdp.name", "STRING", false)
663
664 {
665 _dcmdparser.add_dcmd_option(&_config_file);
666 _dcmdparser.add_dcmd_option(&_jmxremote_host);
667 _dcmdparser.add_dcmd_option(&_jmxremote_port);
668 _dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);
669 _dcmdparser.add_dcmd_option(&_jmxremote_ssl);
670 _dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);
671 _dcmdparser.add_dcmd_option(&_jmxremote_authenticate);
672 _dcmdparser.add_dcmd_option(&_jmxremote_password_file);
673 _dcmdparser.add_dcmd_option(&_jmxremote_access_file);
674 _dcmdparser.add_dcmd_option(&_jmxremote_login_config);
675 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);
676 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
677 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
678 _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
679 _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery);
680 _dcmdparser.add_dcmd_option(&_jdp_port);
681 _dcmdparser.add_dcmd_option(&_jdp_address);
682 _dcmdparser.add_dcmd_option(&_jdp_source_addr);
683 _dcmdparser.add_dcmd_option(&_jdp_ttl);
684 _dcmdparser.add_dcmd_option(&_jdp_pause);
685 _dcmdparser.add_dcmd_option(&_jdp_name);
686 }
687
688 void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
689 ResourceMark rm(THREAD);
690 HandleMark hm(THREAD);
691
692 // Load and initialize the jdk.internal.agent.Agent class
693 // invoke startRemoteManagementAgent(string) method to start
694 // the remote management server.
695 // throw java.lang.NoSuchMethodError if the method doesn't exist
696
697 loadAgentModule(CHECK);
698 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
699 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
700
701 JavaValue result(T_VOID);
702
703 // Pass all command line arguments to java as key=value,...
704 // All checks are done on java side
705
706 int len = 0;
707 stringStream options;
708 char comma[2] = {0,0};
709
710 // Leave default values on Agent.class side and pass only
711 // arguments explicitly set by user. All arguments passed
712 // to jcmd override properties with the same name set by
713 // command line with -D or by managmenent.properties
714 // file.
715 #define PUT_OPTION(a) \
716 do { \
717 if ( (a).is_set() ){ \
718 if ( *((a).type()) == 'I' ) { \
719 options.print("%scom.sun.management.%s=" JLONG_FORMAT, comma, (a).name(), (jlong)((a).value())); \
720 } else { \
721 options.print("%scom.sun.management.%s=%s", comma, (a).name(), (char*)((a).value())); \
722 } \
723 comma[0] = ','; \
724 }\
725 } while(0);
726
727
728 PUT_OPTION(_config_file);
729 PUT_OPTION(_jmxremote_host);
730 PUT_OPTION(_jmxremote_port);
731 PUT_OPTION(_jmxremote_rmi_port);
732 PUT_OPTION(_jmxremote_ssl);
733 PUT_OPTION(_jmxremote_registry_ssl);
734 PUT_OPTION(_jmxremote_authenticate);
735 PUT_OPTION(_jmxremote_password_file);
736 PUT_OPTION(_jmxremote_access_file);
737 PUT_OPTION(_jmxremote_login_config);
738 PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);
739 PUT_OPTION(_jmxremote_ssl_enabled_protocols);
740 PUT_OPTION(_jmxremote_ssl_need_client_auth);
741 PUT_OPTION(_jmxremote_ssl_config_file);
742 PUT_OPTION(_jmxremote_autodiscovery);
743 PUT_OPTION(_jdp_port);
744 PUT_OPTION(_jdp_address);
745 PUT_OPTION(_jdp_source_addr);
746 PUT_OPTION(_jdp_ttl);
747 PUT_OPTION(_jdp_pause);
748 PUT_OPTION(_jdp_name);
749
750 #undef PUT_OPTION
751
752 Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);
753 JavaCalls::call_static(&result, k, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);
754 }
755
756 JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :
757 DCmd(output, heap_allocated) {
758 // do nothing
759 }
760
761 void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
762 ResourceMark rm(THREAD);
763 HandleMark hm(THREAD);
764
765 // Load and initialize the jdk.internal.agent.Agent class
766 // invoke startLocalManagementAgent(void) method to start
767 // the local management server
768 // throw java.lang.NoSuchMethodError if method doesn't exist
769
770 loadAgentModule(CHECK);
771 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
772 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
773
774 JavaValue result(T_VOID);
775 JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
776 }
777
778 void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {
779 ResourceMark rm(THREAD);
780 HandleMark hm(THREAD);
781
782 // Load and initialize the jdk.internal.agent.Agent class
783 // invoke stopRemoteManagementAgent method to stop the
784 // management server
785 // throw java.lang.NoSuchMethodError if method doesn't exist
786
787 loadAgentModule(CHECK);
788 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
789 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
790
791 JavaValue result(T_VOID);
792 JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
793 }
794
795 JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) :
796 DCmd(output, heap_allocated) {
797 // do nothing
798 }
799
800 void JMXStatusDCmd::execute(DCmdSource source, TRAPS) {
801 ResourceMark rm(THREAD);
802 HandleMark hm(THREAD);
803
804 // Load and initialize the jdk.internal.agent.Agent class
805 // invoke getManagementAgentStatus() method to generate the status info
806 // throw java.lang.NoSuchMethodError if method doesn't exist
807
808 loadAgentModule(CHECK);
809 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
810 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
811
812 JavaValue result(T_OBJECT);
813 JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK);
814
815 jvalue* jv = (jvalue*) result.get_value_addr();
816 oop str = cast_to_oop(jv->l);
817 if (str != nullptr) {
818 char* out = java_lang_String::as_utf8_string(str);
819 if (out) {
820 // Avoid using print_cr() because length maybe longer than O_BUFLEN
821 output()->print_raw_cr(out);
822 return;
823 }
824 }
825 output()->print_cr("Error obtaining management agent status");
826 }
827
828 VMDynamicLibrariesDCmd::VMDynamicLibrariesDCmd(outputStream *output, bool heap_allocated) :
829 DCmd(output, heap_allocated) {
830 // do nothing
831 }
832
833 void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) {
834 os::print_dll_info(output());
835 output()->cr();
836 }
837
838 void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
839 VM_PrintCompileQueue printCompileQueueOp(output());
840 VMThread::execute(&printCompileQueueOp);
841 }
842
843 void CodeListDCmd::execute(DCmdSource source, TRAPS) {
844 CodeCache::print_codelist(output());
845 }
846
847 void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
848 CodeCache::print_layout(output());
849 }
850
851 #ifdef LINUX
852 PerfMapDCmd::PerfMapDCmd(outputStream* output, bool heap) :
853 DCmdWithParser(output, heap),
854 _filename("filename", "Name of the map file", "FILE", false, DEFAULT_PERFMAP_FILENAME)
855 {
856 _dcmdparser.add_dcmd_argument(&_filename);
857 }
858
859 void PerfMapDCmd::execute(DCmdSource source, TRAPS) {
860 CodeCache::write_perf_map(_filename.value(), output());
861 }
862 #endif // LINUX
863
864 //---< BEGIN >--- CodeHeap State Analytics.
865 CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) :
866 DCmdWithParser(output, heap),
867 _function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard", "STRING", false, "all"),
868 _granularity("granularity", "Detail level - smaller value -> more detail", "INT", false, "4096") {
869 _dcmdparser.add_dcmd_argument(&_function);
870 _dcmdparser.add_dcmd_argument(&_granularity);
871 }
872
873 void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) {
874 jlong granularity = _granularity.value();
875 if (granularity < 1) {
876 Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
877 "Invalid granularity value " JLONG_FORMAT ". Should be positive.\n", granularity);
878 return;
879 }
880
881 CompileBroker::print_heapinfo(output(), _function.value(), granularity);
882 }
883 //---< END >--- CodeHeap State Analytics.
884
885 EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) :
886 DCmdWithParser(output, heap),
887 _log("log", "Name of log to be printed. If omitted, all logs are printed.", "STRING", false, nullptr),
888 _max("max", "Maximum number of events to be printed (newest first). If omitted or zero, all events are printed.", "INT", false, "0")
889 {
890 _dcmdparser.add_dcmd_option(&_log);
891 _dcmdparser.add_dcmd_option(&_max);
892 }
893
894 void EventLogDCmd::execute(DCmdSource source, TRAPS) {
895 int max = (int)_max.value();
896 if (max < 0) {
897 output()->print_cr("Invalid max option: \"%d\".", max);
898 return;
899 }
900 const char* log_name = _log.value();
901 if (log_name != nullptr) {
902 Events::print_one(output(), log_name, max);
903 } else {
904 Events::print_all(output(), max);
905 }
906 }
907
908 void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {
909 DirectivesStack::print(output());
910 }
911
912 CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :
913 DCmdWithParser(output, heap),
914 _filename("filename","Name of the directives file", "STRING",true) {
915 _dcmdparser.add_dcmd_argument(&_filename);
916 }
917
918 void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {
919 DirectivesParser::parse_from_file(_filename.value(), output(), true);
920 }
921
922 void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
923 DirectivesStack::pop(1);
924 }
925
926 void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
927 DirectivesStack::clear();
928 }
929 #if INCLUDE_SERVICES
930 ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
931 DCmdWithParser(output, heap),
932 _print_interfaces("-i", "Inherited interfaces should be printed.", "BOOLEAN", false, "false"),
933 _print_subclasses("-s", "If a classname is specified, print its subclasses "
934 "in addition to its superclasses. Without this option only the "
935 "superclasses will be printed.", "BOOLEAN", false, "false"),
936 _classname("classname", "Name of class whose hierarchy should be printed. "
937 "If not specified, all class hierarchies are printed.",
938 "STRING", false) {
939 _dcmdparser.add_dcmd_option(&_print_interfaces);
940 _dcmdparser.add_dcmd_option(&_print_subclasses);
941 _dcmdparser.add_dcmd_argument(&_classname);
942 }
943
944 void ClassHierarchyDCmd::execute(DCmdSource source, TRAPS) {
945 VM_PrintClassHierarchy printClassHierarchyOp(output(), _print_interfaces.value(),
946 _print_subclasses.value(), _classname.value());
947 VMThread::execute(&printClassHierarchyOp);
948 }
949
950 PrintClassLayoutDCmd::PrintClassLayoutDCmd(outputStream* output, bool heap) :
951 DCmdWithParser(output, heap),
952 _classname("classname", "Name of class whose layout should be printed. ",
953 "STRING", true) {
954 _dcmdparser.add_dcmd_argument(&_classname);
955 }
956
957 void PrintClassLayoutDCmd::execute(DCmdSource source, TRAPS) {
958 VM_PrintClassLayout printClassLayoutOp(output(), _classname.value());
959 VMThread::execute(&printClassLayoutOp);
960 }
961
962 int PrintClassLayoutDCmd::num_arguments() {
963 ResourceMark rm;
964 PrintClassLayoutDCmd* dcmd = new PrintClassLayoutDCmd(nullptr, false);
965 if (dcmd != nullptr) {
966 DCmdMark mark(dcmd);
967 return dcmd->_dcmdparser.num_arguments();
968 } else {
969 return 0;
970 }
971 }
972
973 #endif // INCLUDE_SERVICES
974
975 ClassesDCmd::ClassesDCmd(outputStream* output, bool heap) :
976 DCmdWithParser(output, heap),
977 _verbose("-verbose",
978 "Dump the detailed content of a Java class. "
979 "Some classes are annotated with flags: "
980 "F = has, or inherits, a non-empty finalize method, "
981 "f = has final method, "
982 "W = methods rewritten, "
983 "C = marked with @Contended annotation, "
984 "R = has been redefined, "
985 "S = is shared class",
986 "BOOLEAN", false, "false") {
987 _dcmdparser.add_dcmd_option(&_verbose);
988 }
989
990 class VM_PrintClasses : public VM_Operation {
991 private:
992 outputStream* _out;
993 bool _verbose;
994 public:
995 VM_PrintClasses(outputStream* out, bool verbose) : _out(out), _verbose(verbose) {}
996
997 virtual VMOp_Type type() const { return VMOp_PrintClasses; }
998
999 virtual void doit() {
1000 PrintClassClosure closure(_out, _verbose);
1001 ClassLoaderDataGraph::classes_do(&closure);
1002 }
1003 };
1004
1005 void ClassesDCmd::execute(DCmdSource source, TRAPS) {
1006 VM_PrintClasses vmop(output(), _verbose.value());
1007 VMThread::execute(&vmop);
1008 }
1009
1010 #if INCLUDE_CDS
1011 void AOTEndRecordingDCmd::execute(DCmdSource source, TRAPS) {
1012 if (!CDSConfig::is_dumping_preimage_static_archive()) {
1013 output()->print_cr("AOT.end_recording is unsupported when VM flags -XX:AOTMode=record or -XX:AOTCacheOutput=<file> are missing.");
1014 return;
1015 }
1016
1017 if (AOTMetaspace::preimage_static_archive_dumped()) {
1018 output()->print_cr("Recording has already ended.");
1019 return;
1020 }
1021
1022 AOTMetaspace::dump_static_archive(THREAD);
1023 if (!AOTMetaspace::preimage_static_archive_dumped()) {
1024 output()->print_cr("Error: Failed to end recording.");
1025 return;
1026 }
1027
1028 output()->print_cr("Recording ended successfully.");
1029 }
1030 #endif // INCLUDE_CDS
1031
1032 #if INCLUDE_CDS
1033 #define DEFAULT_CDS_ARCHIVE_FILENAME "java_pid%p_<subcmd>.jsa"
1034
1035 DumpSharedArchiveDCmd::DumpSharedArchiveDCmd(outputStream* output, bool heap) :
1036 DCmdWithParser(output, heap),
1037 _suboption("subcmd", "static_dump | dynamic_dump", "STRING", true),
1038 _filename("filename", "Name of shared archive to be dumped", "FILE", false,
1039 DEFAULT_CDS_ARCHIVE_FILENAME)
1040 {
1041 _dcmdparser.add_dcmd_argument(&_suboption);
1042 _dcmdparser.add_dcmd_argument(&_filename);
1043 }
1044
1045 void DumpSharedArchiveDCmd::execute(DCmdSource source, TRAPS) {
1046 jboolean is_static;
1047 const char* scmd = _suboption.value();
1048
1049 // The check for _filename.is_set() is because we don't want to use
1050 // DEFAULT_CDS_ARCHIVE_FILENAME, since it is meant as a description
1051 // of the default, not the actual default.
1052 const char* file = _filename.is_set() ? _filename.value() : nullptr;
1053
1054 if (strcmp(scmd, "static_dump") == 0) {
1055 is_static = JNI_TRUE;
1056 output()->print("Static dump: ");
1057 } else if (strcmp(scmd, "dynamic_dump") == 0) {
1058 is_static = JNI_FALSE;
1059 output()->print("Dynamic dump: ");
1060 if (!CDSConfig::is_using_archive()) {
1061 output()->print_cr("Dynamic dump is unsupported when base CDS archive is not loaded");
1062 return;
1063 }
1064 if (!RecordDynamicDumpInfo) {
1065 output()->print_cr("Dump dynamic should run with -XX:+RecordDynamicDumpInfo");
1066 return;
1067 }
1068 } else {
1069 output()->print_cr("Invalid command for VM.cds, valid input is static_dump or dynamic_dump");
1070 return;
1071 }
1072
1073 // call CDS.dumpSharedArchive
1074 Handle fileh;
1075 if (file != nullptr) {
1076 fileh = java_lang_String::create_from_str(file, CHECK);
1077 }
1078 Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
1079 Klass* cds_klass = SystemDictionary::resolve_or_fail(cds_name, true /*throw error*/, CHECK);
1080 JavaValue result(T_OBJECT);
1081 JavaCallArguments args;
1082 args.push_int(is_static);
1083 args.push_oop(fileh);
1084 JavaCalls::call_static(&result,
1085 cds_klass,
1086 vmSymbols::dumpSharedArchive(),
1087 vmSymbols::dumpSharedArchive_signature(),
1088 &args, CHECK);
1089 if (!HAS_PENDING_EXCEPTION) {
1090 assert(result.get_type() == T_OBJECT, "Sanity check");
1091 // result contains the archive name
1092 char* archive_name = java_lang_String::as_utf8_string(result.get_oop());
1093 output()->print_cr("%s", archive_name);
1094 }
1095 }
1096 #endif // INCLUDE_CDS
1097
1098 ThreadDumpToFileDCmd::ThreadDumpToFileDCmd(outputStream* output, bool heap) :
1099 DCmdWithParser(output, heap),
1100 _overwrite("-overwrite", "May overwrite existing file", "BOOLEAN", false, "false"),
1101 _format("-format", "Output format (\"plain\" or \"json\")", "STRING", false, "plain"),
1102 _filepath("filepath", "The file path to the output file", "FILE", true) {
1103 _dcmdparser.add_dcmd_option(&_overwrite);
1104 _dcmdparser.add_dcmd_option(&_format);
1105 _dcmdparser.add_dcmd_argument(&_filepath);
1106 }
1107
1108 void ThreadDumpToFileDCmd::execute(DCmdSource source, TRAPS) {
1109 bool json = (_format.value() != nullptr) && (strcmp(_format.value(), "json") == 0);
1110 char* path = _filepath.value();
1111 bool overwrite = _overwrite.value();
1112 Symbol* name = (json) ? vmSymbols::dumpThreadsToJson_name() : vmSymbols::dumpThreads_name();
1113 dumpToFile(name, vmSymbols::string_bool_byte_array_signature(), path, overwrite, CHECK);
1114 }
1115
1116 void ThreadDumpToFileDCmd::dumpToFile(Symbol* name, Symbol* signature, const char* path, bool overwrite, TRAPS) {
1117 ResourceMark rm(THREAD);
1118 HandleMark hm(THREAD);
1119
1120 Handle h_path = java_lang_String::create_from_str(path, CHECK);
1121
1122 Symbol* sym = vmSymbols::jdk_internal_vm_ThreadDumper();
1123 Klass* k = SystemDictionary::resolve_or_fail(sym, true, CHECK);
1124
1125 // invoke the ThreadDump method to dump to file
1126 JavaValue result(T_OBJECT);
1127 JavaCallArguments args;
1128 args.push_oop(h_path);
1129 args.push_int(overwrite ? JNI_TRUE : JNI_FALSE);
1130 JavaCalls::call_static(&result,
1131 k,
1132 name,
1133 signature,
1134 &args,
1135 THREAD);
1136 if (HAS_PENDING_EXCEPTION) {
1137 java_lang_Throwable::print(PENDING_EXCEPTION, output());
1138 output()->cr();
1139 CLEAR_PENDING_EXCEPTION;
1140 return;
1141 }
1142
1143 // check that result is byte array
1144 oop res = cast_to_oop(result.get_jobject());
1145 assert(res->is_typeArray(), "just checking");
1146 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
1147
1148 // copy the bytes to the output stream
1149 typeArrayOop ba = typeArrayOop(res);
1150 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
1151 output()->print_raw((const char*)addr, ba->length());
1152 }
1153
1154 // Calls a static no-arg method on jdk.internal.vm.JcmdVThreadCommands that returns a byte[] with
1155 // the output. If the method completes successfully then the bytes are copied to the output stream.
1156 // If the method fails then the exception is printed to the output stream.
1157 static void execute_vthread_command(Symbol* method_name, outputStream* output, TRAPS) {
1158 ResourceMark rm(THREAD);
1159 HandleMark hm(THREAD);
1160
1161 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_JcmdVThreadCommands(), true, CHECK);
1162
1163 JavaValue result(T_OBJECT);
1164 JavaCallArguments args;
1165 JavaCalls::call_static(&result,
1166 k,
1167 method_name,
1168 vmSymbols::void_byte_array_signature(),
1169 &args,
1170 THREAD);
1171 if (HAS_PENDING_EXCEPTION) {
1172 java_lang_Throwable::print(PENDING_EXCEPTION, output);
1173 output->cr();
1174 CLEAR_PENDING_EXCEPTION;
1175 return;
1176 }
1177
1178 // copy the bytes to the output stream
1179 oop res = cast_to_oop(result.get_jobject());
1180 typeArrayOop ba = typeArrayOop(res);
1181 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
1182 output->print_raw((const char*)addr, ba->length());
1183 }
1184
1185 void VThreadSchedulerDCmd::execute(DCmdSource source, TRAPS) {
1186 execute_vthread_command(vmSymbols::printScheduler_name(), output(), CHECK);
1187 }
1188
1189 void VThreadPollersDCmd::execute(DCmdSource source, TRAPS) {
1190 execute_vthread_command(vmSymbols::printPollers_name(), output(), CHECK);
1191 }
1192
1193 CompilationMemoryStatisticDCmd::CompilationMemoryStatisticDCmd(outputStream* output, bool heap) :
1194 DCmdWithParser(output, heap),
1195 _verbose("verbose", "Print detailed information", "BOOLEAN", false, "false"),
1196 _legend("legend", "Table mode: print legend", "BOOLEAN", false, "false"),
1197 _minsize("minsize", "Minimum memory size", "MEMORY SIZE", false, "0") {
1198 _dcmdparser.add_dcmd_option(&_verbose);
1199 _dcmdparser.add_dcmd_option(&_minsize);
1200 _dcmdparser.add_dcmd_option(&_legend);
1201 }
1202
1203 void CompilationMemoryStatisticDCmd::execute(DCmdSource source, TRAPS) {
1204 const size_t minsize = _minsize.has_value() ? _minsize.value()._size : 0;
1205 CompilationMemoryStatistic::print_jcmd_report(output(), _verbose.value(), _legend.value(), minsize);
1206 }
1207
1208 #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__)
1209
1210 SystemMapDCmd::SystemMapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
1211
1212 void SystemMapDCmd::execute(DCmdSource source, TRAPS) {
1213 MemMapPrinter::print_all_mappings(output());
1214 }
1215
1216 static constexpr char default_filename[] = "vm_memory_map_%p.txt";
1217
1218 SystemDumpMapDCmd::SystemDumpMapDCmd(outputStream* output, bool heap) :
1219 DCmdWithParser(output, heap),
1220 _filename("-F", "file path", "FILE", false, default_filename) {
1221 _dcmdparser.add_dcmd_option(&_filename);
1222 }
1223
1224 void SystemDumpMapDCmd::execute(DCmdSource source, TRAPS) {
1225 const char* name = _filename.value();
1226 if (name == nullptr || name[0] == 0) {
1227 output()->print_cr("filename is empty or not specified. No file written");
1228 return;
1229 }
1230 fileStream fs(name);
1231 if (fs.is_open()) {
1232 if (!MemTracker::enabled()) {
1233 output()->print_cr("(NMT is disabled, will not annotate mappings).");
1234 }
1235 MemMapPrinter::print_all_mappings(&fs);
1236 // For the readers convenience, resolve path name.
1237 char tmp[JVM_MAXPATHLEN];
1238 const char* absname = os::realpath(name, tmp, sizeof(tmp));
1239 name = absname != nullptr ? absname : name;
1240 output()->print_cr("Memory map dumped to \"%s\".", name);
1241 } else {
1242 output()->print_cr("Failed to open \"%s\" for writing (%s).", name, os::strerror(errno));
1243 }
1244 }
1245
1246 #endif // LINUX