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