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