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