Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit f8df953

Browse files
author
Markus Grönlund
committed
8268702: JFR diagnostic commands lack argument descriptors when viewed using Platform MBean Server
Reviewed-by: egahlin
1 parent c294ae4 commit f8df953

File tree

3 files changed

+101
-10
lines changed

3 files changed

+101
-10
lines changed

src/hotspot/share/jfr/dcmd/jfrDcmds.cpp

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
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"
@@ -33,6 +33,7 @@
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

243243
void 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+
279340
GrowableArray<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

283360
GrowableArray<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

src/hotspot/share/jfr/dcmd/jfrDcmds.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class JfrStartFlightRecordingDCmd : public JfrDCmd {
6565
virtual const char* javaClass() const {
6666
return "jdk/jfr/internal/dcmd/DCmdStart";
6767
}
68+
static int num_arguments() {
69+
return 11;
70+
}
6871
};
6972

7073
class JfrDumpFlightRecordingDCmd : public JfrDCmd {
@@ -87,6 +90,9 @@ class JfrDumpFlightRecordingDCmd : public JfrDCmd {
8790
virtual const char* javaClass() const {
8891
return "jdk/jfr/internal/dcmd/DCmdDump";
8992
}
93+
static int num_arguments() {
94+
return 7;
95+
}
9096
};
9197

9298
class JfrCheckFlightRecordingDCmd : public JfrDCmd {
@@ -109,6 +115,9 @@ class JfrCheckFlightRecordingDCmd : public JfrDCmd {
109115
virtual const char* javaClass() const {
110116
return "jdk/jfr/internal/dcmd/DCmdCheck";
111117
}
118+
static int num_arguments() {
119+
return 2;
120+
}
112121
};
113122

114123
class JfrStopFlightRecordingDCmd : public JfrDCmd {
@@ -131,6 +140,9 @@ class JfrStopFlightRecordingDCmd : public JfrDCmd {
131140
virtual const char* javaClass() const {
132141
return "jdk/jfr/internal/dcmd/DCmdStop";
133142
}
143+
static int num_arguments() {
144+
return 2;
145+
}
134146
};
135147

136148
class JfrConfigureFlightRecorderDCmd : public DCmdWithParser {

src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ abstract class AbstractDCmd {
5858
// Called by native
5959
public abstract String[] printHelp();
6060

61-
// Called by native
61+
// Called by native. The number of arguments for each command is
62+
// reported to the DCmdFramework as a hardcoded number in native.
63+
// This is to avoid an upcall as part of DcmdFramework enumerating existing commands.
64+
// Remember to keep the two sides in synch.
6265
public abstract Argument[] getArgumentInfos();
6366

6467
// Called by native

0 commit comments

Comments
 (0)