1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.hpp" 27 #include "classfile/vmSymbols.hpp" 28 #include "jfr/jfr.hpp" 29 #include "jfr/dcmd/jfrDcmds.hpp" 30 #include "jfr/jni/jfrJavaSupport.hpp" 31 #include "jfr/recorder/jfrRecorder.hpp" 32 #include "jfr/recorder/access/jfrOptionSet.hpp" 33 #include "memory/resourceArea.hpp" 34 #include "oops/oop.inline.hpp" 35 #include "oops/symbol.hpp" 36 #include "runtime/handles.inline.hpp" 37 #include "services/diagnosticArgument.hpp" 38 #include "services/diagnosticFramework.hpp" 39 #include "trace/traceBackend.hpp" 40 #include "utilities/globalDefinitions.hpp" 41 42 #ifdef _WINDOWS 43 #define JFR_FILENAME_EXAMPLE "C:\\Users\\user\\My Recording.jfr" 44 #endif 45 46 #ifdef __APPLE__ 47 #define JFR_FILENAME_EXAMPLE "/Users/user/My Recording.jfr" 48 #endif 49 50 #ifndef JFR_FILENAME_EXAMPLE 51 #define JFR_FILENAME_EXAMPLE "/home/user/My Recording.jfr" 52 #endif 53 54 // JNIHandle management 55 56 // ------------------------------------------------------------------ 57 // push_jni_handle_block 58 // 59 // Push on a new block of JNI handles. 60 static void push_jni_handle_block(Thread* const thread) { 61 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread)); 62 63 // Allocate a new block for JNI handles. 64 // Inlined code from jni_PushLocalFrame() 65 JNIHandleBlock* prev_handles = thread->active_handles(); 66 JNIHandleBlock* entry_handles = JNIHandleBlock::allocate_block(thread); 67 assert(entry_handles != NULL && prev_handles != NULL, "should not be NULL"); 68 entry_handles->set_pop_frame_link(prev_handles); // make sure prev handles get gc'd. 69 thread->set_active_handles(entry_handles); 70 } 71 72 // ------------------------------------------------------------------ 73 // pop_jni_handle_block 74 // 75 // Pop off the current block of JNI handles. 76 static void pop_jni_handle_block(Thread* const thread) { 77 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread)); 78 79 // Release our JNI handle block 80 JNIHandleBlock* entry_handles = thread->active_handles(); 81 JNIHandleBlock* prev_handles = entry_handles->pop_frame_link(); 82 // restore 83 thread->set_active_handles(prev_handles); 84 entry_handles->set_pop_frame_link(NULL); 85 JNIHandleBlock::release_block(entry_handles, thread); // may block 86 } 87 88 class JNIHandleBlockManager : public StackObj { 89 private: 90 Thread* const _thread; 91 public: 92 JNIHandleBlockManager(Thread* thread) : _thread(thread) { 93 push_jni_handle_block(_thread); 94 } 95 96 ~JNIHandleBlockManager() { 97 pop_jni_handle_block(_thread); 98 } 99 }; 100 101 102 static bool is_disabled(outputStream* output) { 103 if (Jfr::is_disabled()) { 104 if (output != NULL) { 105 output->print_cr("Flight Recorder is disabled.\n"); 106 } 107 return true; 108 } 109 return false; 110 } 111 112 static bool is_recorder_instance_created(outputStream* output) { 113 if (!JfrRecorder::is_created()) { 114 if (output != NULL) { 115 output->print_cr("No available recordings.\n"); 116 output->print_cr("Use JFR.start to start a recording.\n"); 117 } 118 return false; 119 } 120 return true; 121 } 122 123 static bool invalid_state(outputStream* out, TRAPS) { 124 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 125 return is_disabled(out); 126 } 127 128 static void print_pending_exception(outputStream* output, oop throwable) { 129 assert(throwable != NULL, "invariant"); 130 131 oop msg = java_lang_Throwable::message(throwable); 132 133 if (msg != NULL) { 134 char* text = java_lang_String::as_utf8_string(msg); 135 output->print_raw_cr(text); 136 } 137 } 138 139 static void print_message(outputStream* output, const char* message) { 140 if (message != NULL) { 141 output->print_raw(message); 142 } 143 } 144 145 static void handle_dcmd_result(outputStream* output, 146 const oop result, 147 const DCmdSource source, 148 TRAPS) { 149 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 150 assert(output != NULL, "invariant"); 151 if (HAS_PENDING_EXCEPTION) { 152 print_pending_exception(output, PENDING_EXCEPTION); 153 // Don't clear excption on startup, JVM should fail initialization. 154 if (DCmd_Source_Internal != source) { 155 CLEAR_PENDING_EXCEPTION; 156 } 157 return; 158 } 159 160 assert(!HAS_PENDING_EXCEPTION, "invariant"); 161 162 if (result != NULL) { 163 const char* result_chars = java_lang_String::as_utf8_string(result); 164 print_message(output, result_chars); 165 } 166 } 167 168 static oop construct_dcmd_instance(JfrJavaArguments* args, TRAPS) { 169 assert(args != NULL, "invariant"); 170 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 171 assert(args->klass() != NULL, "invariant"); 172 args->set_name("<init>", CHECK_NULL); 173 args->set_signature("()V", CHECK_NULL); 174 JfrJavaSupport::new_object(args, CHECK_NULL); 175 return (oop)args->result()->get_jobject(); 176 } 177 178 JfrDumpFlightRecordingDCmd::JfrDumpFlightRecordingDCmd(outputStream* output, 179 bool heap) : DCmdWithParser(output, heap), 180 _name("name", "Recording name, e.g. \\\"My Recording\\\"", "STRING", true, NULL), 181 _filename("filename", "Copy recording data to file, i.e \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", true), 182 _path_to_gc_roots("path-to-gc-roots", "Collect path to GC roots", "BOOLEAN", false, "false") { 183 _dcmdparser.add_dcmd_option(&_name); 184 _dcmdparser.add_dcmd_option(&_filename); 185 _dcmdparser.add_dcmd_option(&_path_to_gc_roots); 186 }; 187 188 int JfrDumpFlightRecordingDCmd::num_arguments() { 189 ResourceMark rm; 190 JfrDumpFlightRecordingDCmd* dcmd = new JfrDumpFlightRecordingDCmd(NULL, false); 191 if (dcmd != NULL) { 192 DCmdMark mark(dcmd); 193 return dcmd->_dcmdparser.num_arguments(); 194 } 195 return 0; 196 } 197 198 void JfrDumpFlightRecordingDCmd::execute(DCmdSource source, TRAPS) { 199 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 200 201 if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) { 202 return; 203 } 204 205 ResourceMark rm(THREAD); 206 HandleMark hm(THREAD); 207 JNIHandleBlockManager jni_handle_management(THREAD); 208 209 JavaValue result(T_OBJECT); 210 JfrJavaArguments constructor_args(&result); 211 constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdDump", CHECK); 212 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK); 213 Handle h_dcmd_instance(THREAD, dcmd); 214 assert(h_dcmd_instance.not_null(), "invariant"); 215 216 jstring name = NULL; 217 if (_name.is_set() && _name.value() != NULL) { 218 name = JfrJavaSupport::new_string(_name.value(), CHECK); 219 } 220 221 jstring filepath = NULL; 222 if (_filename.is_set() && _filename.value() != NULL) { 223 filepath = JfrJavaSupport::new_string(_filename.value(), CHECK); 224 } 225 226 jobject path_to_gc_roots = NULL; 227 if (_path_to_gc_roots.is_set()) { 228 path_to_gc_roots = JfrJavaSupport::new_java_lang_Boolean(_path_to_gc_roots.value(), CHECK); 229 } 230 231 static const char klass[] = "jdk/jfr/internal/dcmd/DCmdDump"; 232 static const char method[] = "execute"; 233 static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;"; 234 235 JfrJavaArguments execute_args(&result, klass, method, signature, CHECK); 236 execute_args.set_receiver(h_dcmd_instance); 237 238 // arguments 239 execute_args.push_jobject(name); 240 execute_args.push_jobject(filepath); 241 execute_args.push_jobject(path_to_gc_roots); 242 243 JfrJavaSupport::call_virtual(&execute_args, THREAD); 244 handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD); 245 } 246 247 JfrCheckFlightRecordingDCmd::JfrCheckFlightRecordingDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), 248 _name("name","Recording text, e.g. \\\"My Recording\\\" or omit to see all recordings","STRING",false, NULL), 249 _verbose("verbose","Print event settings for the recording(s)","BOOLEAN", 250 false, "false") { 251 _dcmdparser.add_dcmd_option(&_name); 252 _dcmdparser.add_dcmd_option(&_verbose); 253 }; 254 255 int JfrCheckFlightRecordingDCmd::num_arguments() { 256 ResourceMark rm; 257 JfrCheckFlightRecordingDCmd* dcmd = new JfrCheckFlightRecordingDCmd(NULL, false); 258 if (dcmd != NULL) { 259 DCmdMark mark(dcmd); 260 return dcmd->_dcmdparser.num_arguments(); 261 } 262 return 0; 263 } 264 265 void JfrCheckFlightRecordingDCmd::execute(DCmdSource source, TRAPS) { 266 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 267 268 if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) { 269 return; 270 } 271 272 ResourceMark rm(THREAD); 273 HandleMark hm(THREAD); 274 JNIHandleBlockManager jni_handle_management(THREAD); 275 276 JavaValue result(T_OBJECT); 277 JfrJavaArguments constructor_args(&result); 278 constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdCheck", CHECK); 279 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK); 280 Handle h_dcmd_instance(THREAD, dcmd); 281 assert(h_dcmd_instance.not_null(), "invariant"); 282 283 jstring name = NULL; 284 if (_name.is_set() && _name.value() != NULL) { 285 name = JfrJavaSupport::new_string(_name.value(), CHECK); 286 } 287 288 jobject verbose = NULL; 289 if (_verbose.is_set()) { 290 verbose = JfrJavaSupport::new_java_lang_Boolean(_verbose.value(), CHECK); 291 } 292 293 static const char klass[] = "jdk/jfr/internal/dcmd/DCmdCheck"; 294 static const char method[] = "execute"; 295 static const char signature[] = "(Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;"; 296 297 JfrJavaArguments execute_args(&result, klass, method, signature, CHECK); 298 execute_args.set_receiver(h_dcmd_instance); 299 300 // arguments 301 execute_args.push_jobject(name); 302 execute_args.push_jobject(verbose); 303 304 JfrJavaSupport::call_virtual(&execute_args, THREAD); 305 handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD); 306 } 307 308 JfrStartFlightRecordingDCmd::JfrStartFlightRecordingDCmd(outputStream* output, 309 bool heap) : DCmdWithParser(output, heap), 310 _name("name", "Name that can be used to identify recording, e.g. \\\"My Recording\\\"", "STRING", false, NULL), 311 _settings("settings", "Settings file(s), e.g. profile or default. See JRE_HOME/lib/jfr", "STRING SET", false), 312 _delay("delay", "Delay recording start with (s)econds, (m)inutes), (h)ours), or (d)ays, e.g. 5h.", "NANOTIME", false, "0"), 313 _duration("duration", "Duration of recording in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 300s.", "NANOTIME", false, "0"), 314 _filename("filename", "Resulting recording filename, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false), 315 _disk("disk", "Recording should be persisted to disk", "BOOLEAN", false), 316 _maxage("maxage", "Maximum time to keep recorded data (on disk) in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or 0 for no limit", "NANOTIME", false, "0"), 317 _maxsize("maxsize", "Maximum amount of bytes to keep (on disk) in (k)B, (M)B or (G)B, e.g. 500M, or 0 for no limit", "MEMORY SIZE", false, "0"), 318 _dump_on_exit("dumponexit", "Dump running recording when JVM shuts down", "BOOLEAN", false), 319 _path_to_gc_roots("path-to-gc-roots", "Collect path to GC roots", "BOOLEAN", false, "false") { 320 _dcmdparser.add_dcmd_option(&_name); 321 _dcmdparser.add_dcmd_option(&_settings); 322 _dcmdparser.add_dcmd_option(&_delay); 323 _dcmdparser.add_dcmd_option(&_duration); 324 _dcmdparser.add_dcmd_option(&_disk); 325 _dcmdparser.add_dcmd_option(&_filename); 326 _dcmdparser.add_dcmd_option(&_maxage); 327 _dcmdparser.add_dcmd_option(&_maxsize); 328 _dcmdparser.add_dcmd_option(&_dump_on_exit); 329 _dcmdparser.add_dcmd_option(&_path_to_gc_roots); 330 }; 331 332 int JfrStartFlightRecordingDCmd::num_arguments() { 333 ResourceMark rm; 334 JfrStartFlightRecordingDCmd* dcmd = new JfrStartFlightRecordingDCmd(NULL, false); 335 if (dcmd != NULL) { 336 DCmdMark mark(dcmd); 337 return dcmd->_dcmdparser.num_arguments(); 338 } 339 return 0; 340 } 341 342 void JfrStartFlightRecordingDCmd::execute(DCmdSource source, TRAPS) { 343 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 344 345 if (invalid_state(output(), THREAD)) { 346 return; 347 } 348 349 ResourceMark rm(THREAD); 350 HandleMark hm(THREAD); 351 JNIHandleBlockManager jni_handle_management(THREAD); 352 353 JavaValue result(T_OBJECT); 354 JfrJavaArguments constructor_args(&result); 355 constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdStart", THREAD); 356 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK); 357 Handle h_dcmd_instance(THREAD, dcmd); 358 assert(h_dcmd_instance.not_null(), "invariant"); 359 360 jstring name = NULL; 361 if (_name.is_set() && _name.value() != NULL) { 362 name = JfrJavaSupport::new_string(_name.value(), CHECK); 363 } 364 365 jstring filename = NULL; 366 if (_filename.is_set() && _filename.value() != NULL) { 367 filename = JfrJavaSupport::new_string(_filename.value(), CHECK); 368 } 369 370 jobject maxage = NULL; 371 if (_maxage.is_set()) { 372 maxage = JfrJavaSupport::new_java_lang_Long(_maxage.value()._nanotime, CHECK); 373 } 374 375 jobject maxsize = NULL; 376 if (_maxsize.is_set()) { 377 maxsize = JfrJavaSupport::new_java_lang_Long(_maxsize.value()._size, CHECK); 378 } 379 380 jobject duration = NULL; 381 if (_duration.is_set()) { 382 duration = JfrJavaSupport::new_java_lang_Long(_duration.value()._nanotime, CHECK); 383 } 384 385 jobject delay = NULL; 386 if (_delay.is_set()) { 387 delay = JfrJavaSupport::new_java_lang_Long(_delay.value()._nanotime, CHECK); 388 } 389 390 jobject disk = NULL; 391 if (_disk.is_set()) { 392 disk = JfrJavaSupport::new_java_lang_Boolean(_disk.value(), CHECK); 393 } 394 395 jobject dump_on_exit = NULL; 396 if (_dump_on_exit.is_set()) { 397 dump_on_exit = JfrJavaSupport::new_java_lang_Boolean(_dump_on_exit.value(), CHECK); 398 } 399 400 jobject path_to_gc_roots = NULL; 401 if (_path_to_gc_roots.is_set()) { 402 path_to_gc_roots = JfrJavaSupport::new_java_lang_Boolean(_path_to_gc_roots.value(), CHECK); 403 } 404 405 jobjectArray settings = NULL; 406 if (_settings.is_set()) { 407 const int length = _settings.value()->array()->length(); 408 settings = JfrJavaSupport::new_string_array(length, CHECK); 409 assert(settings != NULL, "invariant"); 410 for (int i = 0; i < length; ++i) { 411 jobject element = JfrJavaSupport::new_string(_settings.value()->array()->at(i), CHECK); 412 assert(element != NULL, "invariant"); 413 JfrJavaSupport::set_array_element(settings, element, i, CHECK); 414 } 415 } 416 417 static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStart"; 418 static const char method[] = "execute"; 419 static const char signature[] = "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/Long;" 420 "Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/String;" 421 "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/lang/String;"; 422 423 JfrJavaArguments execute_args(&result, klass, method, signature, CHECK); 424 execute_args.set_receiver(h_dcmd_instance); 425 426 // arguments 427 execute_args.push_jobject(name); 428 execute_args.push_jobject(settings); 429 execute_args.push_jobject(delay); 430 execute_args.push_jobject(duration); 431 execute_args.push_jobject(disk); 432 execute_args.push_jobject(filename); 433 execute_args.push_jobject(maxage); 434 execute_args.push_jobject(maxsize); 435 execute_args.push_jobject(dump_on_exit); 436 execute_args.push_jobject(path_to_gc_roots); 437 438 JfrJavaSupport::call_virtual(&execute_args, THREAD); 439 handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD); 440 } 441 442 JfrStopFlightRecordingDCmd::JfrStopFlightRecordingDCmd(outputStream* output, 443 bool heap) : DCmdWithParser(output, heap), 444 _name("name", "Recording text,.e.g \\\"My Recording\\\"", "STRING", false, NULL), 445 _filename("filename", "Copy recording data to file, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false, NULL) { 446 _dcmdparser.add_dcmd_option(&_name); 447 _dcmdparser.add_dcmd_option(&_filename); 448 }; 449 450 int JfrStopFlightRecordingDCmd::num_arguments() { 451 ResourceMark rm; 452 JfrStopFlightRecordingDCmd* dcmd = new JfrStopFlightRecordingDCmd(NULL, false); 453 if (dcmd != NULL) { 454 DCmdMark mark(dcmd); 455 return dcmd->_dcmdparser.num_arguments(); 456 } 457 return 0; 458 } 459 460 void JfrStopFlightRecordingDCmd::execute(DCmdSource source, TRAPS) { 461 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 462 463 if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) { 464 return; 465 } 466 467 ResourceMark rm(THREAD); 468 HandleMark hm(THREAD); 469 JNIHandleBlockManager jni_handle_management(THREAD); 470 471 JavaValue result(T_OBJECT); 472 JfrJavaArguments constructor_args(&result); 473 constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdStop", CHECK); 474 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK); 475 Handle h_dcmd_instance(THREAD, dcmd); 476 assert(h_dcmd_instance.not_null(), "invariant"); 477 478 jstring name = NULL; 479 if (_name.is_set() && _name.value() != NULL) { 480 name = JfrJavaSupport::new_string(_name.value(), CHECK); 481 } 482 483 jstring filepath = NULL; 484 if (_filename.is_set() && _filename.value() != NULL) { 485 filepath = JfrJavaSupport::new_string(_filename.value(), CHECK); 486 } 487 488 static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStop"; 489 static const char method[] = "execute"; 490 static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"; 491 492 JfrJavaArguments execute_args(&result, klass, method, signature, CHECK); 493 execute_args.set_receiver(h_dcmd_instance); 494 495 // arguments 496 execute_args.push_jobject(name); 497 execute_args.push_jobject(filepath); 498 499 JfrJavaSupport::call_virtual(&execute_args, THREAD); 500 handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD); 501 } 502 503 JfrConfigureFlightRecorderDCmd::JfrConfigureFlightRecorderDCmd(outputStream* output, 504 bool heap) : DCmdWithParser(output, heap), 505 _repository_path("repositorypath", "Path to repository,.e.g \\\"My Repository\\\"", "STRING", false, NULL), 506 _dump_path("dumppath", "Path to dump,.e.g \\\"My Dump path\\\"", "STRING", false, NULL), 507 _stack_depth("stackdepth", "Stack Depth", "JLONG", false, "64"), 508 _global_buffer_count("globalbuffercount", "Number of global buffers,", "JLONG", false, "32"), 509 _global_buffer_size("globalbuffersize", "Size of a global buffers,", "JLONG", false, "524288"), 510 _thread_buffer_size("thread_buffer_size", "Size of a thread buffer", "JLONG", false, "8192"), 511 _memory_size("memorysize", "Overall memory size, ", "JLONG", false, "16777216"), 512 _max_chunk_size("maxchunksize", "Size of an individual disk chunk", "JLONG", false, "12582912"), 513 _sample_threads("samplethreads", "Activate Thread sampling", "BOOLEAN", false, "true") { 514 _dcmdparser.add_dcmd_option(&_repository_path); 515 _dcmdparser.add_dcmd_option(&_dump_path); 516 _dcmdparser.add_dcmd_option(&_stack_depth); 517 _dcmdparser.add_dcmd_option(&_global_buffer_count); 518 _dcmdparser.add_dcmd_option(&_global_buffer_size); 519 _dcmdparser.add_dcmd_option(&_thread_buffer_size); 520 _dcmdparser.add_dcmd_option(&_memory_size); 521 _dcmdparser.add_dcmd_option(&_max_chunk_size); 522 _dcmdparser.add_dcmd_option(&_sample_threads); 523 }; 524 525 int JfrConfigureFlightRecorderDCmd::num_arguments() { 526 ResourceMark rm; 527 JfrConfigureFlightRecorderDCmd* dcmd = new JfrConfigureFlightRecorderDCmd(NULL, false); 528 if (dcmd != NULL) { 529 DCmdMark mark(dcmd); 530 return dcmd->_dcmdparser.num_arguments(); 531 } 532 return 0; 533 } 534 535 void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { 536 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 537 538 if (invalid_state(output(), THREAD)) { 539 return; 540 } 541 542 ResourceMark rm(THREAD); 543 HandleMark hm(THREAD); 544 JNIHandleBlockManager jni_handle_management(THREAD); 545 546 JavaValue result(T_OBJECT); 547 JfrJavaArguments constructor_args(&result); 548 constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdConfigure", CHECK); 549 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK); 550 Handle h_dcmd_instance(THREAD, dcmd); 551 assert(h_dcmd_instance.not_null(), "invariant"); 552 553 jstring repository_path = NULL; 554 if (_repository_path.is_set() && _repository_path.value() != NULL) { 555 repository_path = JfrJavaSupport::new_string(_repository_path.value(), CHECK); 556 } 557 558 jstring dump_path = NULL; 559 if (_dump_path.is_set() && _dump_path.value() != NULL) { 560 dump_path = JfrJavaSupport::new_string(_dump_path.value(), CHECK); 561 } 562 563 jobject stack_depth = NULL; 564 if (_stack_depth.is_set()) { 565 stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK); 566 } 567 568 jobject global_buffer_count = NULL; 569 if (_global_buffer_count.is_set()) { 570 global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK); 571 } 572 573 jobject global_buffer_size = NULL; 574 if (_global_buffer_size.is_set()) { 575 global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value(), CHECK); 576 } 577 578 jobject thread_buffer_size = NULL; 579 if (_thread_buffer_size.is_set()) { 580 thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value(), CHECK); 581 } 582 583 jobject max_chunk_size = NULL; 584 if (_max_chunk_size.is_set()) { 585 max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value(), CHECK); 586 } 587 588 jobject memory_size = NULL; 589 if (_memory_size.is_set()) { 590 memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value(), CHECK); 591 } 592 593 jobject sample_threads = NULL; 594 if (_sample_threads.is_set()) { 595 sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK); 596 } 597 598 static const char klass[] = "jdk/jfr/internal/dcmd/DCmdConfigure"; 599 static const char method[] = "execute"; 600 static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;" 601 "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;" 602 "Ljava/lang/Long;Ljava/lang/Boolean;)Ljava/lang/String;"; 603 604 JfrJavaArguments execute_args(&result, klass, method, signature, CHECK); 605 execute_args.set_receiver(h_dcmd_instance); 606 607 // params 608 execute_args.push_jobject(repository_path); 609 execute_args.push_jobject(dump_path); 610 execute_args.push_jobject(stack_depth); 611 execute_args.push_jobject(global_buffer_count); 612 execute_args.push_jobject(global_buffer_size); 613 execute_args.push_jobject(thread_buffer_size); 614 execute_args.push_jobject(memory_size); 615 execute_args.push_jobject(max_chunk_size); 616 execute_args.push_jobject(sample_threads); 617 618 JfrJavaSupport::call_virtual(&execute_args, THREAD); 619 handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD); 620 } 621 622 bool register_jfr_dcmds() { 623 uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean; 624 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrCheckFlightRecordingDCmd>(full_export, true, false)); 625 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrDumpFlightRecordingDCmd>(full_export, true, false)); 626 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStartFlightRecordingDCmd>(full_export, true, false)); 627 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStopFlightRecordingDCmd>(full_export, true, false)); 628 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrConfigureFlightRecorderDCmd>(full_export, true, false)); 629 return true; 630 } 631