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