1 /*
2 * Copyright (c) 2012, 2026, 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 "classfile/javaClasses.inline.hpp"
26 #include "classfile/vmSymbols.hpp"
27 #include "jfr/dcmd/jfrDcmds.hpp"
28 #include "jfr/jfr.hpp"
29 #include "jfr/jni/jfrJavaSupport.hpp"
30 #include "jfr/recorder/jfrRecorder.hpp"
31 #include "jfr/recorder/service/jfrOptionSet.hpp"
32 #include "jfr/support/jfrThreadLocal.hpp"
33 #include "logging/log.hpp"
34 #include "logging/logConfiguration.hpp"
35 #include "logging/logMessage.hpp"
36 #include "memory/arena.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "oops/objArrayOop.inline.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "oops/oopCast.inline.hpp"
41 #include "oops/symbol.hpp"
42 #include "runtime/handles.inline.hpp"
43 #include "runtime/jniHandles.hpp"
44 #include "services/diagnosticArgument.hpp"
45 #include "services/diagnosticFramework.hpp"
46 #include "utilities/globalDefinitions.hpp"
47
48
49 bool register_jfr_dcmds() {
50 uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean;
51 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrCheckFlightRecordingDCmd>(full_export));
52 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrDumpFlightRecordingDCmd>(full_export));
53 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStartFlightRecordingDCmd>(full_export));
54 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStopFlightRecordingDCmd>(full_export));
55 // JFR.query Uncomment when developing new queries for the JFR.view command
56 // DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrQueryFlightRecordingDCmd>(full_export, /*hidden=*/true));
57 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrViewFlightRecordingDCmd>(full_export));
58 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrConfigureFlightRecorderDCmd>(full_export));
59 return true;
60 }
61
62 static bool is_disabled(outputStream* output) {
63 if (Jfr::is_disabled()) {
64 if (output != nullptr) {
65 output->print_cr("Flight Recorder is disabled.\n");
66 }
67 return true;
68 }
69 return false;
70 }
71
72 static bool invalid_state(outputStream* out, TRAPS) {
73 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
74 if (is_disabled(out)) {
75 return true;
76 }
77 if (!JfrJavaSupport::is_jdk_jfr_module_available()) {
78 JfrJavaSupport::load_jdk_jfr_module(THREAD);
79 if (HAS_PENDING_EXCEPTION) {
80 // Log exception here, but let is_jdk_jfr_module_available(out, THREAD)
81 // handle output to the user.
82 ResourceMark rm(THREAD);
83 oop throwable = PENDING_EXCEPTION;
84 assert(throwable != nullptr, "invariant");
85 oop msg = java_lang_Throwable::message(throwable);
86 if (msg != nullptr) {
87 char* text = java_lang_String::as_utf8_string(msg);
88 if (text != nullptr) {
89 log_debug(jfr, startup)("Flight Recorder can not be enabled. %s", text);
90 }
91 }
92 CLEAR_PENDING_EXCEPTION;
93 }
94 }
95 return !JfrJavaSupport::is_jdk_jfr_module_available(out, THREAD);
96 }
97
98 static void handle_pending_exception(outputStream* output, bool startup, oop throwable) {
99 assert(throwable != nullptr, "invariant");
100
101 oop msg = java_lang_Throwable::message(throwable);
102 if (msg == nullptr) {
103 return;
104 }
105 char* text = java_lang_String::as_utf8_string(msg);
106 if (text != nullptr) {
107 if (startup) {
108 log_error(jfr,startup)("%s", text);
109 } else {
110 output->print_cr("%s", text);
111 }
112 }
113 }
114
115 static void print_message(outputStream* output, oop content, TRAPS) {
116 assert(content != nullptr, "invariant");
117 refArrayOop lines = oop_cast<refArrayOop>(content);
118 const int length = lines->length();
119 for (int i = 0; i < length; ++i) {
120 const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
121 if (text == nullptr) {
122 // An oome has been thrown and is pending.
123 break;
124 }
125 output->print_cr("%s", text);
126 }
127 }
128
129 static void log(oop content, TRAPS) {
130 LogMessage(jfr,startup) msg;
131 assert(content != nullptr, "invariant");
132 refArrayOop lines = oop_cast<refArrayOop>(content);
133 const int length = lines->length();
134 for (int i = 0; i < length; ++i) {
135 const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
136 if (text == nullptr) {
137 // An oome has been thrown and is pending.
138 break;
139 }
140 msg.info("%s", text);
141 }
142 }
143
144 static void handle_dcmd_result(outputStream* output,
145 const oop result,
146 const DCmdSource source,
147 TRAPS) {
148 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
149 assert(output != nullptr, "invariant");
150 ResourceMark rm(THREAD);
151 const bool startup = DCmd_Source_Internal == source;
152 if (HAS_PENDING_EXCEPTION) {
153 handle_pending_exception(output, startup, PENDING_EXCEPTION);
154 // Don't clear exception on startup, JVM should fail initialization.
155 if (!startup) {
156 CLEAR_PENDING_EXCEPTION;
157 }
158 return;
159 }
160
161 assert(!HAS_PENDING_EXCEPTION, "invariant");
162
163 if (startup) {
164 if (log_is_enabled(Warning, jfr, startup)) {
165 // if warning is set, assume user hasn't configured log level
166 // Log to Info and reset to Warning. This way user can disable
167 // default output by setting -Xlog:jfr+startup=error/off
168 LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(jfr, startup));
169 log(result, THREAD);
170 LogConfiguration::configure_stdout(LogLevel::Warning, true, LOG_TAGS(jfr, startup));
171 } else {
172 log(result, THREAD);
173 }
174 } else {
175 // Print output for jcmd or MXBean
176 print_message(output, result, THREAD);
177 }
178 }
179
180 static oop construct_dcmd_instance(JfrJavaArguments* args, TRAPS) {
181 assert(args != nullptr, "invariant");
182 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
183 assert(args->klass() != nullptr, "invariant");
184 args->set_name("<init>");
185 args->set_signature("()V");
186 JfrJavaSupport::new_object(args, CHECK_NULL);
187 return args->result()->get_oop();
188 }
189
190 JfrDCmd::JfrDCmd(outputStream* output, bool heap, int num_arguments) : DCmd(output, heap), _args(nullptr), _num_arguments(num_arguments), _delimiter('\0') {}
191
192 void JfrDCmd::invoke(JfrJavaArguments& method, TRAPS) const {
193 JavaValue constructor_result(T_OBJECT);
194 JfrJavaArguments constructor_args(&constructor_result);
195 constructor_args.set_klass(javaClass(), CHECK);
196
197 HandleMark hm(THREAD);
198 JNIHandleMark jni_handle_management(THREAD);
199
200 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
201
202 Handle h_dcmd_instance(THREAD, dcmd);
203 assert(h_dcmd_instance.not_null(), "invariant");
204
205 method.set_receiver(h_dcmd_instance);
206 JfrJavaSupport::call_virtual(&method, THREAD);
207 }
208
209 void JfrDCmd::parse(CmdLine* line, char delim, TRAPS) {
210 _args = line->args_addr();
211 _delimiter = delim;
212 // Error checking done in execute.
213 // Will not matter from DCmdFactory perspective
214 // where parse and execute are called consecutively.
215 }
216
217 void JfrDCmd::execute(DCmdSource source, TRAPS) {
218 if (invalid_state(output(), THREAD)) {
219 return;
220 }
221 if (source == DCmd_Source_Internal && _args != nullptr && strcmp(_args, "help") == 0) {
222 print_java_help("getStartupHelp");
223 vm_exit(0);
224 }
225
226 static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;C)[Ljava/lang/String;";
227 JavaValue result(T_OBJECT);
228 JfrJavaArguments execute(&result, javaClass(), "execute", signature, CHECK);
229 jstring argument = JfrJavaSupport::new_string(_args, CHECK);
230 jstring s = nullptr;
231 if (source == DCmd_Source_Internal) {
232 s = JfrJavaSupport::new_string("internal", CHECK);
233 }
234 if (source == DCmd_Source_MBean) {
235 s = JfrJavaSupport::new_string("mbean", CHECK);
236 }
237 if (source == DCmd_Source_AttachAPI) {
238 s = JfrJavaSupport::new_string("attach", CHECK);
239 }
240 execute.push_jobject(s);
241 execute.push_jobject(argument);
242 execute.push_int(_delimiter);
243 invoke(execute, THREAD);
244 handle_dcmd_result(output(), result.get_oop(), source, THREAD);
245 }
246
247 void JfrDCmd::print_java_help(const char* get_help_method) const {
248 static const char signature[] = "()[Ljava/lang/String;";
249 JavaThread* thread = JavaThread::current();
250 JavaValue result(T_OBJECT);
251 JfrJavaArguments java_method(&result, javaClass(), get_help_method, signature, thread);
252 invoke(java_method, thread);
253 handle_dcmd_result(output(), result.get_oop(), DCmd_Source_MBean, thread);
254 }
255
256 void JfrDCmd::print_help(const char* name) const {
257 print_java_help("getHelp");
258 }
259
260 static void initialize_dummy_descriptors(GrowableArray<DCmdArgumentInfo*>* array) {
261 assert(array != nullptr, "invariant");
262 DCmdArgumentInfo * const dummy = new DCmdArgumentInfo(nullptr,
263 nullptr,
264 nullptr,
265 nullptr,
266 false,
267 true, // a DcmdFramework "option"
268 false);
269 for (int i = 0; i < array->capacity(); ++i) {
270 array->append(dummy);
271 }
272 }
273
274 // Since the DcmdFramework does not support dynamically allocated strings,
275 // we keep them in a thread local arena. The arena is reset between invocations.
276 static THREAD_LOCAL Arena* dcmd_arena = nullptr;
277
278 static void prepare_dcmd_string_arena(JavaThread* jt) {
279 dcmd_arena = JfrThreadLocal::dcmd_arena(jt);
280 assert(dcmd_arena != nullptr, "invariant");
281 dcmd_arena->destruct_contents(); // will grow on next allocation
282 }
283
284 static char* dcmd_arena_allocate(size_t size) {
285 assert(dcmd_arena != nullptr, "invariant");
286 return (char*)dcmd_arena->Amalloc(size);
287 }
288
289 static const char* get_as_dcmd_arena_string(oop string) {
290 char* str = nullptr;
291 const typeArrayOop value = java_lang_String::value(string);
292 if (value != nullptr) {
293 const size_t length = java_lang_String::utf8_length(string, value) + 1;
294 str = dcmd_arena_allocate(length);
295 assert(str != nullptr, "invariant");
296 java_lang_String::as_utf8_string(string, value, str, length);
297 }
298 return str;
299 }
300
301 static const char* read_string_field(oop argument, const char* field_name, TRAPS) {
302 JavaValue result(T_OBJECT);
303 JfrJavaArguments args(&result);
304 args.set_klass(argument->klass());
305 args.set_name(field_name);
306 args.set_signature("Ljava/lang/String;");
307 args.set_receiver(argument);
308 JfrJavaSupport::get_field(&args, THREAD);
309 const oop string_oop = result.get_oop();
310 return string_oop != nullptr ? get_as_dcmd_arena_string(string_oop) : nullptr;
311 }
312
313 static bool read_boolean_field(oop argument, const char* field_name, TRAPS) {
314 JavaValue result(T_BOOLEAN);
315 JfrJavaArguments args(&result);
316 args.set_klass(argument->klass());
317 args.set_name(field_name);
318 args.set_signature("Z");
319 args.set_receiver(argument);
320 JfrJavaSupport::get_field(&args, THREAD);
321 return (result.get_jint() & 1) == 1;
322 }
323
324 static DCmdArgumentInfo* create_info(oop argument, TRAPS) {
325 return new DCmdArgumentInfo(
326 read_string_field(argument, "name", THREAD),
327 read_string_field(argument, "description", THREAD),
328 read_string_field(argument, "type", THREAD),
329 read_string_field(argument, "defaultValue", THREAD),
330 read_boolean_field(argument, "mandatory", THREAD),
331 read_boolean_field(argument, "option", THREAD),
332 read_boolean_field(argument, "allowMultiple", THREAD));
333 }
334
335 GrowableArray<DCmdArgumentInfo*>* JfrDCmd::argument_info_array() const {
336 static const char signature[] = "()[Ljdk/jfr/internal/dcmd/Argument;";
337 JavaThread* thread = JavaThread::current();
338 GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>(_num_arguments);
339 JavaValue result(T_OBJECT);
340 JfrJavaArguments getArgumentInfos(&result, javaClass(), "getArgumentInfos", signature, thread);
341 invoke(getArgumentInfos, thread);
342 if (thread->has_pending_exception()) {
343 // Most likely an OOME, but the DCmdFramework is not the best place to handle it.
344 // We handle it locally by clearing the exception and returning an array with dummy descriptors.
345 // This lets the MBean server initialization routine complete successfully,
346 // but this particular command will have no argument descriptors exposed.
347 // Hence we postpone, or delegate, handling of OOME's to code that is better suited.
348 log_debug(jfr, system)("Exception in DCmd getArgumentInfos");
349 thread->clear_pending_exception();
350 initialize_dummy_descriptors(array);
351 assert(array->length() == _num_arguments, "invariant");
352 return array;
353 }
354 oop oop_args = result.get_oop();
355 assert(oop_args != nullptr, "invariant");
356 refArrayOop arguments = oop_cast<refArrayOop>(oop_args);
357 const int num_arguments = arguments->length();
358 assert(num_arguments == _num_arguments, "invariant");
359 prepare_dcmd_string_arena(thread);
360 for (int i = 0; i < num_arguments; ++i) {
361 DCmdArgumentInfo* const dai = create_info(arguments->obj_at(i), thread);
362 assert(dai != nullptr, "invariant");
363 array->append(dai);
364 }
365 return array;
366 }
367
368 GrowableArray<const char*>* JfrDCmd::argument_name_array() const {
369 GrowableArray<DCmdArgumentInfo*>* argument_infos = argument_info_array();
370 GrowableArray<const char*>* array = new GrowableArray<const char*>(argument_infos->length());
371 for (int i = 0; i < argument_infos->length(); i++) {
372 array->append(argument_infos->at(i)->name());
373 }
374 return array;
375 }
376
377 JfrConfigureFlightRecorderDCmd::JfrConfigureFlightRecorderDCmd(outputStream* output,
378 bool heap) : DCmdWithParser(output, heap),
379 _repository_path("repositorypath", "Path to repository,.e.g \\\"My Repository\\\"", "STRING", false, nullptr),
380 _dump_path("dumppath", "Path to dump, e.g. \\\"My Dump path\\\"", "STRING", false, nullptr),
381 _stack_depth("stackdepth", "Stack depth", "JULONG", false, "64"),
382 _global_buffer_count("globalbuffercount", "Number of global buffers,", "JULONG", false, "20"),
383 _global_buffer_size("globalbuffersize", "Size of a global buffers,", "MEMORY SIZE", false, "512k"),
384 _thread_buffer_size("thread_buffer_size", "Size of a thread buffer", "MEMORY SIZE", false, "8k"),
385 _memory_size("memorysize", "Overall memory size, ", "MEMORY SIZE", false, "10m"),
386 _max_chunk_size("maxchunksize", "Size of an individual disk chunk", "MEMORY SIZE", false, "12m"),
387 _sample_threads("samplethreads", "Activate thread sampling", "BOOLEAN", false, "true"),
388 _preserve_repository("preserve-repository", "Preserve the disk repository after JVM exit", "BOOLEAN", false, "false"),
389 _verbose(true) {
390 _dcmdparser.add_dcmd_option(&_repository_path);
391 _dcmdparser.add_dcmd_option(&_dump_path);
392 _dcmdparser.add_dcmd_option(&_stack_depth);
393 _dcmdparser.add_dcmd_option(&_global_buffer_count);
394 _dcmdparser.add_dcmd_option(&_global_buffer_size);
395 _dcmdparser.add_dcmd_option(&_thread_buffer_size);
396 _dcmdparser.add_dcmd_option(&_memory_size);
397 _dcmdparser.add_dcmd_option(&_max_chunk_size);
398 _dcmdparser.add_dcmd_option(&_sample_threads);
399 _dcmdparser.add_dcmd_option(&_preserve_repository);
400 };
401
402 void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const {
403 outputStream* out = output();
404 // 0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890
405 out->print_cr("Options:");
406 out->print_cr("");
407 out->print_cr(" globalbuffercount (Optional) Number of global buffers. This option is a legacy");
408 out->print_cr(" option: change the memorysize parameter to alter the number of");
409 out->print_cr(" global buffers. This value cannot be changed once JFR has been");
410 out->print_cr(" initialized. (STRING, default determined by the value for");
411 out->print_cr(" memorysize)");
412 out->print_cr("");
413 out->print_cr(" globalbuffersize (Optional) Size of the global buffers, in bytes. This option is a");
414 out->print_cr(" legacy option: change the memorysize parameter to alter the size");
415 out->print_cr(" of the global buffers. This value cannot be changed once JFR has");
416 out->print_cr(" been initialized. (STRING, default determined by the value for");
417 out->print_cr(" memorysize)");
418 out->print_cr("");
419 out->print_cr(" maxchunksize (Optional) Maximum size of an individual data chunk in bytes if");
420 out->print_cr(" one of the following suffixes is not used: 'm' or 'M' for");
421 out->print_cr(" megabytes OR 'g' or 'G' for gigabytes. This value cannot be");
422 out->print_cr(" changed once JFR has been initialized. (STRING, 12M)");
423 out->print_cr("");
424 out->print_cr(" memorysize (Optional) Overall memory size, in bytes if one of the following");
425 out->print_cr(" suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for");
426 out->print_cr(" gigabytes. This value cannot be changed once JFR has been");
427 out->print_cr(" initialized. (STRING, 10M)");
428 out->print_cr("");
429 out->print_cr(" repositorypath (Optional) Path to the location where recordings are stored until");
430 out->print_cr(" they are written to a permanent file. (STRING, The default");
431 out->print_cr(" location is the temporary directory for the operating system. On");
432 out->print_cr(" Linux operating systems, the temporary directory is /tmp. On");
433 out->print_cr(" Windows, the temporary directory is specified by the TMP");
434 out->print_cr(" environment variable)");
435 out->print_cr("");
436 out->print_cr(" dumppath (Optional) Path to the location where a recording file is written");
437 out->print_cr(" in case the VM runs into a critical error, such as a system");
438 out->print_cr(" crash. (STRING, The default location is the current directory)");
439 out->print_cr("");
440 out->print_cr(" stackdepth (Optional) Stack depth for stack traces. Setting this value");
441 out->print_cr(" greater than the default of 64 may cause a performance");
442 out->print_cr(" degradation. This value cannot be changed once JFR has been");
443 out->print_cr(" initialized. (LONG, 64)");
444 out->print_cr("");
445 out->print_cr(" thread_buffer_size (Optional) Local buffer size for each thread in bytes if one of");
446 out->print_cr(" the following suffixes is not used: 'k' or 'K' for kilobytes or");
447 out->print_cr(" 'm' or 'M' for megabytes. Overriding this parameter could reduce");
448 out->print_cr(" performance and is not recommended. This value cannot be changed");
449 out->print_cr(" once JFR has been initialized. (STRING, 8k)");
450 out->print_cr("");
451 out->print_cr(" preserve-repository (Optional) Preserve files stored in the disk repository after the");
452 out->print_cr(" Java Virtual Machine has exited. (BOOLEAN, false)");
453 out->print_cr("");
454 out->print_cr("Options must be specified using the <key> or <key>=<value> syntax.");
455 out->print_cr("");
456 out->print_cr("Example usage:");
457 out->print_cr("");
458 out->print_cr(" $ jcmd <pid> JFR.configure");
459 out->print_cr(" $ jcmd <pid> JFR.configure repositorypath=/temporary");
460 out->print_cr(" $ jcmd <pid> JFR.configure stackdepth=256");
461 out->print_cr(" $ jcmd <pid> JFR.configure memorysize=100M");
462 out->print_cr("");
463 }
464
465 void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
466 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
467
468 if (invalid_state(output(), THREAD)) {
469 return;
470 }
471
472 HandleMark hm(THREAD);
473 JNIHandleMark jni_handle_management(THREAD);
474
475 JavaValue result(T_OBJECT);
476 JfrJavaArguments constructor_args(&result);
477 constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdConfigure", CHECK);
478 const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
479 Handle h_dcmd_instance(THREAD, dcmd);
480 assert(h_dcmd_instance.not_null(), "invariant");
481
482 jstring repository_path = nullptr;
483 if (_repository_path.is_set() && _repository_path.value() != nullptr) {
484 repository_path = JfrJavaSupport::new_string(_repository_path.value(), CHECK);
485 }
486
487 jstring dump_path = nullptr;
488 if (_dump_path.is_set() && _dump_path.value() != nullptr) {
489 dump_path = JfrJavaSupport::new_string(_dump_path.value(), CHECK);
490 }
491
492 jobject stack_depth = nullptr;
493 jobject global_buffer_count = nullptr;
494 jobject global_buffer_size = nullptr;
495 jobject thread_buffer_size = nullptr;
496 jobject max_chunk_size = nullptr;
497 jobject memory_size = nullptr;
498 jobject preserve_repository = nullptr;
499
500 if (!JfrRecorder::is_created()) {
501 if (_stack_depth.is_set()) {
502 stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK);
503 }
504 if (_global_buffer_count.is_set()) {
505 global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK);
506 }
507 if (_global_buffer_size.is_set()) {
508 global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value()._size, CHECK);
509 }
510 if (_thread_buffer_size.is_set()) {
511 thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value()._size, CHECK);
512 }
513 if (_max_chunk_size.is_set()) {
514 max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value()._size, CHECK);
515 }
516 if (_memory_size.is_set()) {
517 memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK);
518 }
519 if (_sample_threads.is_set()) {
520 bool startup = DCmd_Source_Internal == source;
521 if (startup) {
522 log_warning(jfr,startup)("%s", "Option samplethreads is deprecated. Use -XX:StartFlightRecording:method-profiling=<off|normal|high|max>");
523 } else {
524 output()->print_cr("%s", "Option samplethreads is deprecated. Use JFR.start method-profiling=<off|normal|high|max>");
525 output()->print_cr("");
526 }
527 }
528 }
529 if (_preserve_repository.is_set()) {
530 preserve_repository = JfrJavaSupport::new_java_lang_Boolean(_preserve_repository.value(), CHECK);
531 }
532
533 static const char klass[] = "jdk/jfr/internal/dcmd/DCmdConfigure";
534 static const char method[] = "execute";
535 static const char signature[] = "(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Integer;"
536 "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;"
537 "Ljava/lang/Long;Ljava/lang/Boolean;)[Ljava/lang/String;";
538
539 JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
540 execute_args.set_receiver(h_dcmd_instance);
541
542 // params
543 execute_args.push_int(_verbose ? 1 : 0);
544 execute_args.push_jobject(repository_path);
545 execute_args.push_jobject(dump_path);
546 execute_args.push_jobject(stack_depth);
547 execute_args.push_jobject(global_buffer_count);
548 execute_args.push_jobject(global_buffer_size);
549 execute_args.push_jobject(thread_buffer_size);
550 execute_args.push_jobject(memory_size);
551 execute_args.push_jobject(max_chunk_size);
552 execute_args.push_jobject(preserve_repository);
553
554 JfrJavaSupport::call_virtual(&execute_args, THREAD);
555 handle_dcmd_result(output(), result.get_oop(), source, THREAD);
556 }