Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/services/diagnosticCommand.cpp
64440 views
1
/*
2
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "jvm.h"
27
#include "classfile/classLoaderHierarchyDCmd.hpp"
28
#include "classfile/classLoaderStats.hpp"
29
#include "classfile/javaClasses.hpp"
30
#include "classfile/systemDictionary.hpp"
31
#include "classfile/vmClasses.hpp"
32
#include "code/codeCache.hpp"
33
#include "compiler/compileBroker.hpp"
34
#include "compiler/directivesParser.hpp"
35
#include "gc/shared/gcVMOperations.hpp"
36
#include "memory/metaspace/metaspaceDCmd.hpp"
37
#include "memory/resourceArea.hpp"
38
#include "memory/universe.hpp"
39
#include "oops/objArrayOop.inline.hpp"
40
#include "oops/oop.inline.hpp"
41
#include "oops/typeArrayOop.inline.hpp"
42
#include "runtime/fieldDescriptor.inline.hpp"
43
#include "runtime/flags/jvmFlag.hpp"
44
#include "runtime/handles.inline.hpp"
45
#include "runtime/interfaceSupport.inline.hpp"
46
#include "runtime/javaCalls.hpp"
47
#include "runtime/jniHandles.hpp"
48
#include "runtime/os.hpp"
49
#include "runtime/vmOperations.hpp"
50
#include "runtime/vm_version.hpp"
51
#include "services/diagnosticArgument.hpp"
52
#include "services/diagnosticCommand.hpp"
53
#include "services/diagnosticFramework.hpp"
54
#include "services/heapDumper.hpp"
55
#include "services/management.hpp"
56
#include "services/writeableFlags.hpp"
57
#include "utilities/debug.hpp"
58
#include "utilities/events.hpp"
59
#include "utilities/formatBuffer.hpp"
60
#include "utilities/macros.hpp"
61
#ifdef LINUX
62
#include "trimCHeapDCmd.hpp"
63
#endif
64
65
static void loadAgentModule(TRAPS) {
66
ResourceMark rm(THREAD);
67
HandleMark hm(THREAD);
68
69
JavaValue result(T_OBJECT);
70
Handle h_module_name = java_lang_String::create_from_str("jdk.management.agent", CHECK);
71
JavaCalls::call_static(&result,
72
vmClasses::module_Modules_klass(),
73
vmSymbols::loadModule_name(),
74
vmSymbols::loadModule_signature(),
75
h_module_name,
76
THREAD);
77
}
78
79
void DCmdRegistrant::register_dcmds(){
80
// Registration of the diagnostic commands
81
// First argument specifies which interfaces will export the command
82
// Second argument specifies if the command is enabled
83
// Third argument specifies if the command is hidden
84
uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI
85
| DCmd_Source_MBean;
86
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(full_export, true, false));
87
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(full_export, true, false));
88
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(full_export, true, false));
89
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(full_export, true, false));
90
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(full_export, true, false));
91
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SetVMFlagDCmd>(full_export, true, false));
92
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMDynamicLibrariesDCmd>(full_export, true, false));
93
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export, true, false));
94
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMInfoDCmd>(full_export, true, false));
95
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export, true, false));
96
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));
97
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export, true, false));
98
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export, true, false));
99
#if INCLUDE_SERVICES
100
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
101
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
102
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDictionaryDCmd>(full_export, true, false));
103
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export, true, false));
104
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export, true, false));
105
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export, true, false));
106
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<metaspace::MetaspaceDCmd>(full_export, true, false));
107
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<EventLogDCmd>(full_export, true, false));
108
#if INCLUDE_JVMTI // Both JVMTI and SERVICES have to be enabled to have this dcmd
109
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIAgentLoadDCmd>(full_export, true, false));
110
#endif // INCLUDE_JVMTI
111
#endif // INCLUDE_SERVICES
112
#if INCLUDE_JVMTI
113
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIDataDumpDCmd>(full_export, true, false));
114
#endif // INCLUDE_JVMTI
115
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
116
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
117
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderHierarchyDCmd>(full_export, true, false));
118
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
119
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
120
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
121
#ifdef LINUX
122
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PerfMapDCmd>(full_export, true, false));
123
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TrimCLibcHeapDCmd>(full_export, true, false));
124
#endif // LINUX
125
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));
126
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeHeapAnalyticsDCmd>(full_export, true, false));
127
128
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesPrintDCmd>(full_export, true, false));
129
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesAddDCmd>(full_export, true, false));
130
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesRemoveDCmd>(full_export, true, false));
131
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesClearDCmd>(full_export, true, false));
132
133
// Enhanced JMX Agent Support
134
// These commands won't be exported via the DiagnosticCommandMBean until an
135
// appropriate permission is created for them
136
uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI;
137
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(jmx_agent_export_flags, true,false));
138
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(jmx_agent_export_flags, true,false));
139
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags, true,false));
140
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStatusDCmd>(jmx_agent_export_flags, true,false));
141
142
// Debug on cmd (only makes sense with JVMTI since the agentlib needs it).
143
#if INCLUDE_JVMTI
144
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DebugOnCmdStartDCmd>(full_export, true, true));
145
#endif // INCLUDE_JVMTI
146
147
#if INCLUDE_CDS
148
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DumpSharedArchiveDCmd>(full_export, true, false));
149
#endif // INCLUDE_CDS
150
}
151
152
#ifndef HAVE_EXTRA_DCMD
153
void DCmdRegistrant::register_dcmds_ext(){
154
// Do nothing here
155
}
156
#endif
157
158
159
HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
160
_all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
161
_cmd("command name", "The name of the command for which we want help",
162
"STRING", false) {
163
_dcmdparser.add_dcmd_option(&_all);
164
_dcmdparser.add_dcmd_argument(&_cmd);
165
};
166
167
168
static int compare_strings(const char** s1, const char** s2) {
169
return ::strcmp(*s1, *s2);
170
}
171
172
void HelpDCmd::execute(DCmdSource source, TRAPS) {
173
if (_all.value()) {
174
GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(source);
175
cmd_list->sort(compare_strings);
176
for (int i = 0; i < cmd_list->length(); i++) {
177
DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
178
strlen(cmd_list->at(i)));
179
output()->print_cr("%s%s", factory->name(),
180
factory->is_enabled() ? "" : " [disabled]");
181
output()->print_cr("\t%s", factory->description());
182
output()->cr();
183
factory = factory->next();
184
}
185
} else if (_cmd.has_value()) {
186
DCmd* cmd = NULL;
187
DCmdFactory* factory = DCmdFactory::factory(source, _cmd.value(),
188
strlen(_cmd.value()));
189
if (factory != NULL) {
190
output()->print_cr("%s%s", factory->name(),
191
factory->is_enabled() ? "" : " [disabled]");
192
output()->print_cr("%s", factory->description());
193
output()->print_cr("\nImpact: %s", factory->impact());
194
JavaPermission p = factory->permission();
195
if(p._class != NULL) {
196
if(p._action != NULL) {
197
output()->print_cr("\nPermission: %s(%s, %s)",
198
p._class, p._name == NULL ? "null" : p._name, p._action);
199
} else {
200
output()->print_cr("\nPermission: %s(%s)",
201
p._class, p._name == NULL ? "null" : p._name);
202
}
203
}
204
output()->cr();
205
cmd = factory->create_resource_instance(output());
206
if (cmd != NULL) {
207
DCmdMark mark(cmd);
208
cmd->print_help(factory->name());
209
}
210
} else {
211
output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());
212
}
213
} else {
214
output()->print_cr("The following commands are available:");
215
GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list(source);
216
cmd_list->sort(compare_strings);
217
for (int i = 0; i < cmd_list->length(); i++) {
218
DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
219
strlen(cmd_list->at(i)));
220
output()->print_cr("%s%s", factory->name(),
221
factory->is_enabled() ? "" : " [disabled]");
222
factory = factory->_next;
223
}
224
output()->print_cr("\nFor more information about a specific command use 'help <command>'.");
225
}
226
}
227
228
void VersionDCmd::execute(DCmdSource source, TRAPS) {
229
output()->print_cr("%s version %s", VM_Version::vm_name(),
230
VM_Version::vm_release());
231
JDK_Version jdk_version = JDK_Version::current();
232
if (jdk_version.patch_version() > 0) {
233
output()->print_cr("JDK %d.%d.%d.%d", jdk_version.major_version(),
234
jdk_version.minor_version(), jdk_version.security_version(),
235
jdk_version.patch_version());
236
} else {
237
output()->print_cr("JDK %d.%d.%d", jdk_version.major_version(),
238
jdk_version.minor_version(), jdk_version.security_version());
239
}
240
}
241
242
PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :
243
DCmdWithParser(output, heap),
244
_all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") {
245
_dcmdparser.add_dcmd_option(&_all);
246
}
247
248
void PrintVMFlagsDCmd::execute(DCmdSource source, TRAPS) {
249
if (_all.value()) {
250
JVMFlag::printFlags(output(), true);
251
} else {
252
JVMFlag::printSetFlags(output());
253
}
254
}
255
256
SetVMFlagDCmd::SetVMFlagDCmd(outputStream* output, bool heap) :
257
DCmdWithParser(output, heap),
258
_flag("flag name", "The name of the flag we want to set",
259
"STRING", true),
260
_value("string value", "The value we want to set", "STRING", false) {
261
_dcmdparser.add_dcmd_argument(&_flag);
262
_dcmdparser.add_dcmd_argument(&_value);
263
}
264
265
void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) {
266
const char* val = NULL;
267
if (_value.value() != NULL) {
268
val = _value.value();
269
}
270
271
FormatBuffer<80> err_msg("%s", "");
272
int ret = WriteableFlags::set_flag(_flag.value(), val, JVMFlagOrigin::MANAGEMENT, err_msg);
273
274
if (ret != JVMFlag::SUCCESS) {
275
output()->print_cr("%s", err_msg.buffer());
276
}
277
}
278
279
void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) {
280
if (JvmtiExport::should_post_data_dump()) {
281
JvmtiExport::post_data_dump();
282
}
283
}
284
285
#if INCLUDE_SERVICES
286
#if INCLUDE_JVMTI
287
JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) :
288
DCmdWithParser(output, heap),
289
_libpath("library path", "Absolute path of the JVMTI agent to load.",
290
"STRING", true),
291
_option("agent option", "Option string to pass the agent.", "STRING", false) {
292
_dcmdparser.add_dcmd_argument(&_libpath);
293
_dcmdparser.add_dcmd_argument(&_option);
294
}
295
296
void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) {
297
298
if (_libpath.value() == NULL) {
299
output()->print_cr("JVMTI.agent_load dcmd needs library path.");
300
return;
301
}
302
303
char *suffix = strrchr(_libpath.value(), '.');
304
bool is_java_agent = (suffix != NULL) && (strncmp(".jar", suffix, 4) == 0);
305
306
if (is_java_agent) {
307
if (_option.value() == NULL) {
308
JvmtiExport::load_agent_library("instrument", "false",
309
_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 == NULL) {
319
output()->print_cr("JVMTI agent attach failed: "
320
"Could not allocate " SIZE_FORMAT " bytes for argument.",
321
opt_len);
322
return;
323
}
324
325
jio_snprintf(opt, opt_len, "%s=%s", _libpath.value(), _option.value());
326
JvmtiExport::load_agent_library("instrument", "false", opt, output());
327
328
os::free(opt);
329
}
330
} else {
331
JvmtiExport::load_agent_library(_libpath.value(), "true",
332
_option.value(), output());
333
}
334
}
335
336
#endif // INCLUDE_JVMTI
337
#endif // INCLUDE_SERVICES
338
339
void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
340
// load VMSupport
341
Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport();
342
Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK);
343
InstanceKlass* ik = InstanceKlass::cast(k);
344
if (ik->should_be_initialized()) {
345
ik->initialize(THREAD);
346
}
347
if (HAS_PENDING_EXCEPTION) {
348
java_lang_Throwable::print(PENDING_EXCEPTION, output());
349
output()->cr();
350
CLEAR_PENDING_EXCEPTION;
351
return;
352
}
353
354
// invoke the serializePropertiesToByteArray method
355
JavaValue result(T_OBJECT);
356
JavaCallArguments args;
357
358
Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();
359
JavaCalls::call_static(&result,
360
ik,
361
vmSymbols::serializePropertiesToByteArray_name(),
362
signature,
363
&args,
364
THREAD);
365
if (HAS_PENDING_EXCEPTION) {
366
java_lang_Throwable::print(PENDING_EXCEPTION, output());
367
output()->cr();
368
CLEAR_PENDING_EXCEPTION;
369
return;
370
}
371
372
// The result should be a [B
373
oop res = result.get_oop();
374
assert(res->is_typeArray(), "just checking");
375
assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
376
377
// copy the bytes to the output stream
378
typeArrayOop ba = typeArrayOop(res);
379
jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
380
output()->print_raw((const char*)addr, ba->length());
381
}
382
383
VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
384
DCmdWithParser(output, heap),
385
_date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
386
_dcmdparser.add_dcmd_option(&_date);
387
}
388
389
void VMUptimeDCmd::execute(DCmdSource source, TRAPS) {
390
if (_date.value()) {
391
output()->date_stamp(true, "", ": ");
392
}
393
output()->time_stamp().update_to(tty->time_stamp().ticks());
394
output()->stamp();
395
output()->print_cr(" s");
396
}
397
398
void VMInfoDCmd::execute(DCmdSource source, TRAPS) {
399
VMError::print_vm_info(_output);
400
}
401
402
void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
403
Universe::heap()->collect(GCCause::_dcmd_gc_run);
404
}
405
406
void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {
407
Klass* k = vmClasses::System_klass();
408
JavaValue result(T_VOID);
409
JavaCalls::call_static(&result, k,
410
vmSymbols::run_finalization_name(),
411
vmSymbols::void_method_signature(), CHECK);
412
}
413
414
void HeapInfoDCmd::execute(DCmdSource source, TRAPS) {
415
MutexLocker hl(THREAD, Heap_lock);
416
Universe::heap()->print_on(output());
417
}
418
419
void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) {
420
ResourceMark rm(THREAD);
421
422
Klass* k = SystemDictionary::resolve_or_fail(
423
vmSymbols::finalizer_histogram_klass(), true, CHECK);
424
425
JavaValue result(T_ARRAY);
426
427
// We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method
428
// and expect it to return array of FinalizerHistogramEntry as Object[]
429
430
JavaCalls::call_static(&result, k,
431
vmSymbols::get_finalizer_histogram_name(),
432
vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK);
433
434
objArrayOop result_oop = (objArrayOop) result.get_oop();
435
if (result_oop->length() == 0) {
436
output()->print_cr("No instances waiting for finalization found");
437
return;
438
}
439
440
oop foop = result_oop->obj_at(0);
441
InstanceKlass* ik = InstanceKlass::cast(foop->klass());
442
443
fieldDescriptor count_fd, name_fd;
444
445
Klass* count_res = ik->find_field(
446
vmSymbols::finalizer_histogram_entry_count_field(), vmSymbols::int_signature(), &count_fd);
447
448
Klass* name_res = ik->find_field(
449
vmSymbols::finalizer_histogram_entry_name_field(), vmSymbols::string_signature(), &name_fd);
450
451
assert(count_res != NULL && name_res != NULL, "Unexpected layout of FinalizerHistogramEntry");
452
453
output()->print_cr("Unreachable instances waiting for finalization");
454
output()->print_cr("#instances class name");
455
output()->print_cr("-----------------------");
456
457
for (int i = 0; i < result_oop->length(); ++i) {
458
oop element_oop = result_oop->obj_at(i);
459
oop str_oop = element_oop->obj_field(name_fd.offset());
460
char *name = java_lang_String::as_utf8_string(str_oop);
461
int count = element_oop->int_field(count_fd.offset());
462
output()->print_cr("%10d %s", count, name);
463
}
464
}
465
466
#if INCLUDE_SERVICES // Heap dumping/inspection supported
467
HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
468
DCmdWithParser(output, heap),
469
_filename("filename","Name of the dump file", "STRING",true),
470
_all("-all", "Dump all objects, including unreachable objects",
471
"BOOLEAN", false, "false"),
472
_gzip("-gz", "If specified, the heap dump is written in gzipped format "
473
"using the given compression level. 1 (recommended) is the fastest, "
474
"9 the strongest compression.", "INT", false, "1"),
475
_overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists",
476
"BOOLEAN", false, "false") {
477
_dcmdparser.add_dcmd_option(&_all);
478
_dcmdparser.add_dcmd_argument(&_filename);
479
_dcmdparser.add_dcmd_option(&_gzip);
480
_dcmdparser.add_dcmd_option(&_overwrite);
481
}
482
483
void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
484
jlong level = -1; // -1 means no compression.
485
486
if (_gzip.is_set()) {
487
level = _gzip.value();
488
489
if (level < 1 || level > 9) {
490
output()->print_cr("Compression level out of range (1-9): " JLONG_FORMAT, level);
491
return;
492
}
493
}
494
495
// Request a full GC before heap dump if _all is false
496
// This helps reduces the amount of unreachable objects in the dump
497
// and makes it easier to browse.
498
HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
499
dumper.dump(_filename.value(), output(), (int) level, _overwrite.value());
500
}
501
502
ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
503
DCmdWithParser(output, heap),
504
_all("-all", "Inspect all objects, including unreachable objects",
505
"BOOLEAN", false, "false"),
506
_parallel_thread_num("-parallel",
507
"Number of parallel threads to use for heap inspection. "
508
"0 (the default) means let the VM determine the number of threads to use. "
509
"1 means use one thread (disable parallelism). "
510
"For any other value the VM will try to use the specified number of "
511
"threads, but might use fewer.",
512
"INT", false, "0") {
513
_dcmdparser.add_dcmd_option(&_all);
514
_dcmdparser.add_dcmd_option(&_parallel_thread_num);
515
}
516
517
void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {
518
jlong num = _parallel_thread_num.value();
519
if (num < 0) {
520
output()->print_cr("Parallel thread number out of range (>=0): " JLONG_FORMAT, num);
521
return;
522
}
523
uint parallel_thread_num = num == 0
524
? MAX2<uint>(1, (uint)os::initial_active_processor_count() * 3 / 8)
525
: num;
526
VM_GC_HeapInspection heapop(output(),
527
!_all.value(), /* request full gc if false */
528
parallel_thread_num);
529
VMThread::execute(&heapop);
530
}
531
532
#endif // INCLUDE_SERVICES
533
534
ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
535
DCmdWithParser(output, heap),
536
_locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false"),
537
_extended("-e", "print extended thread information", "BOOLEAN", false, "false") {
538
_dcmdparser.add_dcmd_option(&_locks);
539
_dcmdparser.add_dcmd_option(&_extended);
540
}
541
542
void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) {
543
// thread stacks
544
VM_PrintThreads op1(output(), _locks.value(), _extended.value());
545
VMThread::execute(&op1);
546
547
// JNI global handles
548
VM_PrintJNI op2(output());
549
VMThread::execute(&op2);
550
551
// Deadlock detection
552
VM_FindDeadlocks op3(output());
553
VMThread::execute(&op3);
554
}
555
556
// Enhanced JMX Agent support
557
558
JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :
559
560
DCmdWithParser(output, heap_allocated),
561
562
_config_file
563
("config.file",
564
"set com.sun.management.config.file", "STRING", false),
565
566
_jmxremote_host
567
("jmxremote.host",
568
"set com.sun.management.jmxremote.host", "STRING", false),
569
570
_jmxremote_port
571
("jmxremote.port",
572
"set com.sun.management.jmxremote.port", "STRING", false),
573
574
_jmxremote_rmi_port
575
("jmxremote.rmi.port",
576
"set com.sun.management.jmxremote.rmi.port", "STRING", false),
577
578
_jmxremote_ssl
579
("jmxremote.ssl",
580
"set com.sun.management.jmxremote.ssl", "STRING", false),
581
582
_jmxremote_registry_ssl
583
("jmxremote.registry.ssl",
584
"set com.sun.management.jmxremote.registry.ssl", "STRING", false),
585
586
_jmxremote_authenticate
587
("jmxremote.authenticate",
588
"set com.sun.management.jmxremote.authenticate", "STRING", false),
589
590
_jmxremote_password_file
591
("jmxremote.password.file",
592
"set com.sun.management.jmxremote.password.file", "STRING", false),
593
594
_jmxremote_access_file
595
("jmxremote.access.file",
596
"set com.sun.management.jmxremote.access.file", "STRING", false),
597
598
_jmxremote_login_config
599
("jmxremote.login.config",
600
"set com.sun.management.jmxremote.login.config", "STRING", false),
601
602
_jmxremote_ssl_enabled_cipher_suites
603
("jmxremote.ssl.enabled.cipher.suites",
604
"set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),
605
606
_jmxremote_ssl_enabled_protocols
607
("jmxremote.ssl.enabled.protocols",
608
"set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),
609
610
_jmxremote_ssl_need_client_auth
611
("jmxremote.ssl.need.client.auth",
612
"set com.sun.management.jmxremote.need.client.auth", "STRING", false),
613
614
_jmxremote_ssl_config_file
615
("jmxremote.ssl.config.file",
616
"set com.sun.management.jmxremote.ssl.config.file", "STRING", false),
617
618
// JDP Protocol support
619
_jmxremote_autodiscovery
620
("jmxremote.autodiscovery",
621
"set com.sun.management.jmxremote.autodiscovery", "STRING", false),
622
623
_jdp_port
624
("jdp.port",
625
"set com.sun.management.jdp.port", "INT", false),
626
627
_jdp_address
628
("jdp.address",
629
"set com.sun.management.jdp.address", "STRING", false),
630
631
_jdp_source_addr
632
("jdp.source_addr",
633
"set com.sun.management.jdp.source_addr", "STRING", false),
634
635
_jdp_ttl
636
("jdp.ttl",
637
"set com.sun.management.jdp.ttl", "INT", false),
638
639
_jdp_pause
640
("jdp.pause",
641
"set com.sun.management.jdp.pause", "INT", false),
642
643
_jdp_name
644
("jdp.name",
645
"set com.sun.management.jdp.name", "STRING", false)
646
647
{
648
_dcmdparser.add_dcmd_option(&_config_file);
649
_dcmdparser.add_dcmd_option(&_jmxremote_host);
650
_dcmdparser.add_dcmd_option(&_jmxremote_port);
651
_dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);
652
_dcmdparser.add_dcmd_option(&_jmxremote_ssl);
653
_dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);
654
_dcmdparser.add_dcmd_option(&_jmxremote_authenticate);
655
_dcmdparser.add_dcmd_option(&_jmxremote_password_file);
656
_dcmdparser.add_dcmd_option(&_jmxremote_access_file);
657
_dcmdparser.add_dcmd_option(&_jmxremote_login_config);
658
_dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);
659
_dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
660
_dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
661
_dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
662
_dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery);
663
_dcmdparser.add_dcmd_option(&_jdp_port);
664
_dcmdparser.add_dcmd_option(&_jdp_address);
665
_dcmdparser.add_dcmd_option(&_jdp_source_addr);
666
_dcmdparser.add_dcmd_option(&_jdp_ttl);
667
_dcmdparser.add_dcmd_option(&_jdp_pause);
668
_dcmdparser.add_dcmd_option(&_jdp_name);
669
}
670
671
void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
672
ResourceMark rm(THREAD);
673
HandleMark hm(THREAD);
674
675
// Load and initialize the jdk.internal.agent.Agent class
676
// invoke startRemoteManagementAgent(string) method to start
677
// the remote management server.
678
// throw java.lang.NoSuchMethodError if the method doesn't exist
679
680
loadAgentModule(CHECK);
681
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
682
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
683
684
JavaValue result(T_VOID);
685
686
// Pass all command line arguments to java as key=value,...
687
// All checks are done on java side
688
689
int len = 0;
690
stringStream options;
691
char comma[2] = {0,0};
692
693
// Leave default values on Agent.class side and pass only
694
// agruments explicitly set by user. All arguments passed
695
// to jcmd override properties with the same name set by
696
// command line with -D or by managmenent.properties
697
// file.
698
#define PUT_OPTION(a) \
699
do { \
700
if ( (a).is_set() ){ \
701
if ( *((a).type()) == 'I' ) { \
702
options.print("%scom.sun.management.%s=" JLONG_FORMAT, comma, (a).name(), (jlong)((a).value())); \
703
} else { \
704
options.print("%scom.sun.management.%s=%s", comma, (a).name(), (char*)((a).value())); \
705
} \
706
comma[0] = ','; \
707
}\
708
} while(0);
709
710
711
PUT_OPTION(_config_file);
712
PUT_OPTION(_jmxremote_host);
713
PUT_OPTION(_jmxremote_port);
714
PUT_OPTION(_jmxremote_rmi_port);
715
PUT_OPTION(_jmxremote_ssl);
716
PUT_OPTION(_jmxremote_registry_ssl);
717
PUT_OPTION(_jmxremote_authenticate);
718
PUT_OPTION(_jmxremote_password_file);
719
PUT_OPTION(_jmxremote_access_file);
720
PUT_OPTION(_jmxremote_login_config);
721
PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);
722
PUT_OPTION(_jmxremote_ssl_enabled_protocols);
723
PUT_OPTION(_jmxremote_ssl_need_client_auth);
724
PUT_OPTION(_jmxremote_ssl_config_file);
725
PUT_OPTION(_jmxremote_autodiscovery);
726
PUT_OPTION(_jdp_port);
727
PUT_OPTION(_jdp_address);
728
PUT_OPTION(_jdp_source_addr);
729
PUT_OPTION(_jdp_ttl);
730
PUT_OPTION(_jdp_pause);
731
PUT_OPTION(_jdp_name);
732
733
#undef PUT_OPTION
734
735
Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);
736
JavaCalls::call_static(&result, k, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);
737
}
738
739
JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :
740
DCmd(output, heap_allocated) {
741
// do nothing
742
}
743
744
void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
745
ResourceMark rm(THREAD);
746
HandleMark hm(THREAD);
747
748
// Load and initialize the jdk.internal.agent.Agent class
749
// invoke startLocalManagementAgent(void) method to start
750
// the local management server
751
// throw java.lang.NoSuchMethodError if method doesn't exist
752
753
loadAgentModule(CHECK);
754
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
755
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
756
757
JavaValue result(T_VOID);
758
JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
759
}
760
761
void JMXStopRemoteDCmd::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 stopRemoteManagementAgent method to stop the
767
// 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, Handle(), true, CHECK);
773
774
JavaValue result(T_VOID);
775
JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
776
}
777
778
JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) :
779
DCmd(output, heap_allocated) {
780
// do nothing
781
}
782
783
void JMXStatusDCmd::execute(DCmdSource source, TRAPS) {
784
ResourceMark rm(THREAD);
785
HandleMark hm(THREAD);
786
787
// Load and initialize the jdk.internal.agent.Agent class
788
// invoke getManagementAgentStatus() method to generate the status info
789
// throw java.lang.NoSuchMethodError if method doesn't exist
790
791
loadAgentModule(CHECK);
792
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
793
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
794
795
JavaValue result(T_OBJECT);
796
JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK);
797
798
jvalue* jv = (jvalue*) result.get_value_addr();
799
oop str = cast_to_oop(jv->l);
800
if (str != NULL) {
801
char* out = java_lang_String::as_utf8_string(str);
802
if (out) {
803
output()->print_cr("%s", out);
804
return;
805
}
806
}
807
output()->print_cr("Error obtaining management agent status");
808
}
809
810
VMDynamicLibrariesDCmd::VMDynamicLibrariesDCmd(outputStream *output, bool heap_allocated) :
811
DCmd(output, heap_allocated) {
812
// do nothing
813
}
814
815
void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) {
816
os::print_dll_info(output());
817
output()->cr();
818
}
819
820
void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
821
VM_PrintCompileQueue printCompileQueueOp(output());
822
VMThread::execute(&printCompileQueueOp);
823
}
824
825
void CodeListDCmd::execute(DCmdSource source, TRAPS) {
826
CodeCache::print_codelist(output());
827
}
828
829
void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
830
CodeCache::print_layout(output());
831
}
832
833
#ifdef LINUX
834
void PerfMapDCmd::execute(DCmdSource source, TRAPS) {
835
CodeCache::write_perf_map();
836
}
837
#endif // LINUX
838
839
//---< BEGIN >--- CodeHeap State Analytics.
840
CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) :
841
DCmdWithParser(output, heap),
842
_function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard", "STRING", false, "all"),
843
_granularity("granularity", "Detail level - smaller value -> more detail", "INT", false, "4096") {
844
_dcmdparser.add_dcmd_argument(&_function);
845
_dcmdparser.add_dcmd_argument(&_granularity);
846
}
847
848
void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) {
849
jlong granularity = _granularity.value();
850
if (granularity < 1) {
851
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
852
"Invalid granularity value " JLONG_FORMAT ". Should be positive.\n", granularity);
853
return;
854
}
855
856
CompileBroker::print_heapinfo(output(), _function.value(), granularity);
857
}
858
//---< END >--- CodeHeap State Analytics.
859
860
EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) :
861
DCmdWithParser(output, heap),
862
_log("log", "Name of log to be printed. If omitted, all logs are printed.", "STRING", false, NULL),
863
_max("max", "Maximum number of events to be printed (newest first). If omitted, all events are printed.", "STRING", false, NULL)
864
{
865
_dcmdparser.add_dcmd_option(&_log);
866
_dcmdparser.add_dcmd_option(&_max);
867
}
868
869
void EventLogDCmd::execute(DCmdSource source, TRAPS) {
870
const char* max_value = _max.value();
871
long max = -1;
872
if (max_value != NULL) {
873
char* endptr = NULL;
874
max = ::strtol(max_value, &endptr, 10);
875
if (max == 0 && max_value == endptr) {
876
output()->print_cr("Invalid max option: \"%s\".", max_value);
877
return;
878
}
879
}
880
const char* log_name = _log.value();
881
if (log_name != NULL) {
882
Events::print_one(output(), log_name, max);
883
} else {
884
Events::print_all(output(), max);
885
}
886
}
887
888
void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {
889
DirectivesStack::print(output());
890
}
891
892
CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :
893
DCmdWithParser(output, heap),
894
_filename("filename","Name of the directives file", "STRING",true) {
895
_dcmdparser.add_dcmd_argument(&_filename);
896
}
897
898
void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {
899
DirectivesParser::parse_from_file(_filename.value(), output());
900
}
901
902
void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
903
DirectivesStack::pop(1);
904
}
905
906
void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
907
DirectivesStack::clear();
908
}
909
#if INCLUDE_SERVICES
910
ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
911
DCmdWithParser(output, heap),
912
_print_interfaces("-i", "Inherited interfaces should be printed.", "BOOLEAN", false, "false"),
913
_print_subclasses("-s", "If a classname is specified, print its subclasses. "
914
"Otherwise only its superclasses are printed.", "BOOLEAN", false, "false"),
915
_classname("classname", "Name of class whose hierarchy should be printed. "
916
"If not specified, all class hierarchies are printed.",
917
"STRING", false) {
918
_dcmdparser.add_dcmd_option(&_print_interfaces);
919
_dcmdparser.add_dcmd_option(&_print_subclasses);
920
_dcmdparser.add_dcmd_argument(&_classname);
921
}
922
923
void ClassHierarchyDCmd::execute(DCmdSource source, TRAPS) {
924
VM_PrintClassHierarchy printClassHierarchyOp(output(), _print_interfaces.value(),
925
_print_subclasses.value(), _classname.value());
926
VMThread::execute(&printClassHierarchyOp);
927
}
928
#endif
929
930
class VM_DumpTouchedMethods : public VM_Operation {
931
private:
932
outputStream* _out;
933
public:
934
VM_DumpTouchedMethods(outputStream* out) {
935
_out = out;
936
}
937
938
virtual VMOp_Type type() const { return VMOp_DumpTouchedMethods; }
939
940
virtual void doit() {
941
Method::print_touched_methods(_out);
942
}
943
};
944
945
void TouchedMethodsDCmd::execute(DCmdSource source, TRAPS) {
946
if (!LogTouchedMethods) {
947
output()->print_cr("VM.print_touched_methods command requires -XX:+LogTouchedMethods");
948
return;
949
}
950
VM_DumpTouchedMethods dumper(output());
951
VMThread::execute(&dumper);
952
}
953
954
#if INCLUDE_CDS
955
DumpSharedArchiveDCmd::DumpSharedArchiveDCmd(outputStream* output, bool heap) :
956
DCmdWithParser(output, heap),
957
_suboption("subcmd", "static_dump | dynamic_dump", "STRING", true),
958
_filename("filename", "Name of shared archive to be dumped", "STRING", false)
959
{
960
_dcmdparser.add_dcmd_argument(&_suboption);
961
_dcmdparser.add_dcmd_argument(&_filename);
962
}
963
964
void DumpSharedArchiveDCmd::execute(DCmdSource source, TRAPS) {
965
jboolean is_static;
966
const char* scmd = _suboption.value();
967
const char* file = _filename.value();
968
969
if (strcmp(scmd, "static_dump") == 0) {
970
is_static = JNI_TRUE;
971
output()->print_cr("Static dump:");
972
} else if (strcmp(scmd, "dynamic_dump") == 0) {
973
is_static = JNI_FALSE;
974
output()->print_cr("Dynamic dump:");
975
if (!UseSharedSpaces) {
976
output()->print_cr("Dynamic dump is unsupported when base CDS archive is not loaded");
977
return;
978
}
979
if (!RecordDynamicDumpInfo) {
980
output()->print_cr("Dump dynamic should run with -XX:+RecordDynamicDumpInfo");
981
return;
982
}
983
} else {
984
output()->print_cr("Invalid command for VM.cds, valid input is static_dump or dynamic_dump");
985
return;
986
}
987
988
// call CDS.dumpSharedArchive
989
Handle fileh;
990
if (file != NULL) {
991
fileh = java_lang_String::create_from_str(_filename.value(), CHECK);
992
}
993
Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
994
Klass* cds_klass = SystemDictionary::resolve_or_fail(cds_name, true /*throw error*/, CHECK);
995
JavaValue result(T_VOID);
996
JavaCallArguments args;
997
args.push_int(is_static);
998
args.push_oop(fileh);
999
JavaCalls::call_static(&result,
1000
cds_klass,
1001
vmSymbols::dumpSharedArchive(),
1002
vmSymbols::dumpSharedArchive_signature(),
1003
&args, CHECK);
1004
}
1005
#endif // INCLUDE_CDS
1006
1007
#if INCLUDE_JVMTI
1008
extern "C" typedef char const* (JNICALL *debugInit_startDebuggingViaCommandPtr)(JNIEnv* env, jthread thread, char const** transport_name,
1009
char const** address, jboolean* first_start);
1010
static debugInit_startDebuggingViaCommandPtr dvc_start_ptr = NULL;
1011
1012
void DebugOnCmdStartDCmd::execute(DCmdSource source, TRAPS) {
1013
char const* transport = NULL;
1014
char const* addr = NULL;
1015
jboolean is_first_start = JNI_FALSE;
1016
JavaThread* thread = THREAD;
1017
jthread jt = JNIHandles::make_local(thread->threadObj());
1018
ThreadToNativeFromVM ttn(thread);
1019
const char *error = "Could not find jdwp agent.";
1020
1021
if (!dvc_start_ptr) {
1022
for (AgentLibrary* agent = Arguments::agents(); agent != NULL; agent = agent->next()) {
1023
if ((strcmp("jdwp", agent->name()) == 0) && (dvc_start_ptr == NULL)) {
1024
char const* func = "debugInit_startDebuggingViaCommand";
1025
dvc_start_ptr = (debugInit_startDebuggingViaCommandPtr) os::find_agent_function(agent, false, &func, 1);
1026
}
1027
}
1028
}
1029
1030
if (dvc_start_ptr) {
1031
error = dvc_start_ptr(thread->jni_environment(), jt, &transport, &addr, &is_first_start);
1032
}
1033
1034
if (error != NULL) {
1035
output()->print_cr("Debugging has not been started: %s", error);
1036
} else {
1037
output()->print_cr(is_first_start ? "Debugging has been started." : "Debugging is already active.");
1038
output()->print_cr("Transport : %s", transport ? transport : "#unknown");
1039
output()->print_cr("Address : %s", addr ? addr : "#unknown");
1040
}
1041
}
1042
#endif // INCLUDE_JVMTI
1043
1044