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