2323 */
2424
2525#include " precompiled.hpp"
26- #include " classfile/javaClasses.hpp"
26+ #include " classfile/javaClasses.inline. hpp"
2727#include " classfile/vmSymbols.hpp"
2828#include " jfr/jfr.hpp"
2929#include " jfr/dcmd/jfrDcmds.hpp"
3333#include " logging/log.hpp"
3434#include " logging/logConfiguration.hpp"
3535#include " logging/logMessage.hpp"
36+ #include " memory/arena.hpp"
3637#include " memory/resourceArea.hpp"
3738#include " oops/objArrayOop.inline.hpp"
3839#include " oops/oop.inline.hpp"
@@ -219,7 +220,6 @@ void JfrDCmd::invoke(JfrJavaArguments& method, TRAPS) const {
219220 JfrJavaArguments constructor_args (&constructor_result);
220221 constructor_args.set_klass (javaClass (), CHECK);
221222
222- ResourceMark rm (THREAD);
223223 HandleMark hm (THREAD);
224224 JNIHandleBlockManager jni_handle_management (THREAD);
225225
@@ -241,12 +241,10 @@ void JfrDCmd::parse(CmdLine* line, char delim, TRAPS) {
241241}
242242
243243void JfrDCmd::execute (DCmdSource source, TRAPS) {
244- static const char signature[] = " (Ljava/lang/String;Ljava/lang/String;C)[Ljava/lang/String;" ;
245-
246244 if (invalid_state (output (), THREAD)) {
247245 return ;
248246 }
249-
247+ static const char signature[] = " (Ljava/lang/String;Ljava/lang/String;C)[Ljava/lang/String; " ;
250248 JavaValue result (T_OBJECT);
251249 JfrJavaArguments execute (&result, javaClass (), " execute" , signature, CHECK);
252250 jstring argument = JfrJavaSupport::new_string (_args, CHECK);
@@ -271,13 +269,92 @@ void JfrDCmd::print_help(const char* name) const {
271269 static const char signature[] = " ()[Ljava/lang/String;" ;
272270 JavaThread* thread = JavaThread::current ();
273271 JavaValue result (T_OBJECT);
274- JfrJavaArguments print_help (&result, javaClass (), " printHelp" , signature, thread);
275- invoke (print_help , thread);
272+ JfrJavaArguments printHelp (&result, javaClass (), " printHelp" , signature, thread);
273+ invoke (printHelp , thread);
276274 handle_dcmd_result (output (), result.get_oop (), DCmd_Source_MBean, thread);
277275}
278276
277+ // Since the DcmdFramework does not support dynamically allocated strings,
278+ // we keep them in a thread local arena. The arena is reset between invocations.
279+ static THREAD_LOCAL Arena* dcmd_arena = NULL ;
280+
281+ static void prepare_dcmd_string_arena () {
282+ if (dcmd_arena == NULL ) {
283+ dcmd_arena = new (mtTracing) Arena (mtTracing);
284+ } else {
285+ dcmd_arena->destruct_contents (); // will grow on next allocation
286+ }
287+ }
288+
289+ static char * dcmd_arena_allocate (size_t size) {
290+ assert (dcmd_arena != NULL , " invariant" );
291+ return (char *)dcmd_arena->Amalloc (size);
292+ }
293+
294+ static const char * get_as_dcmd_arena_string (oop string, JavaThread* t) {
295+ char * str = NULL ;
296+ const typeArrayOop value = java_lang_String::value (string);
297+ if (value != NULL ) {
298+ const size_t length = static_cast <size_t >(java_lang_String::utf8_length (string, value)) + 1 ;
299+ str = dcmd_arena_allocate (length);
300+ assert (str != NULL , " invariant" );
301+ java_lang_String::as_utf8_string (string, value, str, static_cast <int >(length));
302+ }
303+ return str;
304+ }
305+
306+ static const char * read_string_field (oop argument, const char * field_name, TRAPS) {
307+ JavaValue result (T_OBJECT);
308+ JfrJavaArguments args (&result);
309+ args.set_klass (argument->klass ());
310+ args.set_name (field_name);
311+ args.set_signature (" Ljava/lang/String;" );
312+ args.set_receiver (argument);
313+ JfrJavaSupport::get_field (&args, THREAD);
314+ const oop string_oop = result.get_oop ();
315+ return string_oop != NULL ? get_as_dcmd_arena_string (string_oop, (JavaThread*)THREAD) : NULL ;
316+ }
317+
318+ static bool read_boolean_field (oop argument, const char * field_name, TRAPS) {
319+ JavaValue result (T_BOOLEAN);
320+ JfrJavaArguments args (&result);
321+ args.set_klass (argument->klass ());
322+ args.set_name (field_name);
323+ args.set_signature (" Z" );
324+ args.set_receiver (argument);
325+ JfrJavaSupport::get_field (&args, THREAD);
326+ return (result.get_jint () & 1 ) == 1 ;
327+ }
328+
329+ static DCmdArgumentInfo* create_info (oop argument, TRAPS) {
330+ return new DCmdArgumentInfo (
331+ read_string_field (argument, " name" , THREAD),
332+ read_string_field (argument, " description" , THREAD),
333+ read_string_field (argument, " type" , THREAD),
334+ read_string_field (argument, " defaultValue" , THREAD),
335+ read_boolean_field (argument, " mandatory" , THREAD),
336+ true , // a DcmdFramework "option"
337+ read_boolean_field (argument, " allowMultiple" , THREAD));
338+ }
339+
279340GrowableArray<DCmdArgumentInfo*>* JfrDCmd::argument_info_array () const {
280- return new GrowableArray<DCmdArgumentInfo*>();
341+ static const char signature[] = " ()[Ljdk/jfr/internal/dcmd/Argument;" ;
342+ JavaThread* thread = JavaThread::current ();
343+ JavaValue result (T_OBJECT);
344+ JfrJavaArguments getArgumentInfos (&result, javaClass (), " getArgumentInfos" , signature, thread);
345+ invoke (getArgumentInfos, thread);
346+ objArrayOop arguments = objArrayOop (result.get_oop ());
347+ assert (arguments != NULL , " invariant" );
348+ assert (arguments->is_array (), " must be array" );
349+ GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>();
350+ const int length = arguments->length ();
351+ prepare_dcmd_string_arena ();
352+ for (int i = 0 ; i < length; ++i) {
353+ DCmdArgumentInfo* const dai = create_info (arguments->obj_at (i), thread);
354+ assert (dai != NULL , " invariant" );
355+ array->append (dai);
356+ }
357+ return array;
281358}
282359
283360GrowableArray<const char *>* JfrDCmd::argument_name_array () const {
@@ -387,7 +464,6 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
387464 return ;
388465 }
389466
390- ResourceMark rm (THREAD);
391467 HandleMark hm (THREAD);
392468 JNIHandleBlockManager jni_handle_management (THREAD);
393469
0 commit comments