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

Commit

Permalink
8270491: SEGV at read_string_field(oopDesc*, char const*, JavaThread*…
Browse files Browse the repository at this point in the history
…)+0x54

Reviewed-by: egahlin
  • Loading branch information
Markus Grönlund committed Jul 27, 2021
1 parent cea7bc2 commit f662127
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 24 deletions.
59 changes: 44 additions & 15 deletions src/hotspot/share/jfr/dcmd/jfrDcmds.cpp
Expand Up @@ -154,19 +154,19 @@ static void print_message(outputStream* output, oop content, TRAPS) {
}

static void log(oop content, TRAPS) {
LogMessage(jfr,startup) msg;
objArrayOop lines = objArrayOop(content);
assert(lines != NULL, "invariant");
assert(lines->is_array(), "must be array");
const int length = lines->length();
for (int i = 0; i < length; ++i) {
const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
if (text == NULL) {
// An oome has been thrown and is pending.
break;
}
msg.info("%s", text);
LogMessage(jfr,startup) msg;
objArrayOop lines = objArrayOop(content);
assert(lines != NULL, "invariant");
assert(lines->is_array(), "must be array");
const int length = lines->length();
for (int i = 0; i < length; ++i) {
const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
if (text == NULL) {
// An oome has been thrown and is pending.
break;
}
msg.info("%s", text);
}
}

static void handle_dcmd_result(outputStream* output,
Expand Down Expand Up @@ -215,6 +215,8 @@ static oop construct_dcmd_instance(JfrJavaArguments* args, TRAPS) {
return args->result()->get_oop();
}

JfrDCmd::JfrDCmd(outputStream* output, bool heap, int num_arguments) : DCmd(output, heap), _args(NULL), _num_arguments(num_arguments), _delimiter('\0') {}

void JfrDCmd::invoke(JfrJavaArguments& method, TRAPS) const {
JavaValue constructor_result(T_OBJECT);
JfrJavaArguments constructor_args(&constructor_result);
Expand Down Expand Up @@ -274,6 +276,20 @@ void JfrDCmd::print_help(const char* name) const {
handle_dcmd_result(output(), result.get_oop(), DCmd_Source_MBean, thread);
}

static void initialize_dummy_descriptors(GrowableArray<DCmdArgumentInfo*>* array) {
assert(array != NULL, "invariant");
DCmdArgumentInfo * const dummy = new DCmdArgumentInfo(NULL,
NULL,
NULL,
NULL,
false,
true, // a DcmdFramework "option"
false);
for (int i = 0; i < array->max_length(); ++i) {
array->append(dummy);
}
}

// Since the DcmdFramework does not support dynamically allocated strings,
// we keep them in a thread local arena. The arena is reset between invocations.
static THREAD_LOCAL Arena* dcmd_arena = NULL;
Expand Down Expand Up @@ -340,16 +356,29 @@ static DCmdArgumentInfo* create_info(oop argument, TRAPS) {
GrowableArray<DCmdArgumentInfo*>* JfrDCmd::argument_info_array() const {
static const char signature[] = "()[Ljdk/jfr/internal/dcmd/Argument;";
JavaThread* thread = JavaThread::current();
GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>(_num_arguments);
JavaValue result(T_OBJECT);
JfrJavaArguments getArgumentInfos(&result, javaClass(), "getArgumentInfos", signature, thread);
invoke(getArgumentInfos, thread);
if (thread->has_pending_exception()) {
// Most likely an OOME, but the DCmdFramework is not the best place to handle it.
// We handle it locally by clearing the exception and returning an array with dummy descriptors.
// This lets the MBean server initialization routine complete successfully,
// but this particular command will have no argument descriptors exposed.
// Hence we postpone, or delegate, handling of OOME's to code that is better suited.
log_debug(jfr, system)("Exception in DCmd getArgumentInfos");
thread->clear_pending_exception();
initialize_dummy_descriptors(array);
assert(array->length() == _num_arguments, "invariant");
return array;
}
objArrayOop arguments = objArrayOop(result.get_oop());
assert(arguments != NULL, "invariant");
assert(arguments->is_array(), "must be array");
GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>();
const int length = arguments->length();
const int num_arguments = arguments->length();
assert(num_arguments == _num_arguments, "invariant");
prepare_dcmd_string_arena();
for (int i = 0; i < length; ++i) {
for (int i = 0; i < num_arguments; ++i) {
DCmdArgumentInfo* const dai = create_info(arguments->obj_at(i), thread);
assert(dai != NULL, "invariant");
array->append(dai);
Expand Down
18 changes: 9 additions & 9 deletions src/hotspot/share/jfr/dcmd/jfrDcmds.hpp
Expand Up @@ -31,23 +31,23 @@ class JfrJavaArguments;
class JfrDCmd : public DCmd {
private:
const char* _args;
const int _num_arguments;
char _delimiter;
protected:
JfrDCmd(outputStream* output, bool heap, int num_arguments);
virtual const char* javaClass() const = 0;
void invoke(JfrJavaArguments& method, TRAPS) const;
public:
JfrDCmd(outputStream* output, bool heap) : DCmd(output,heap), _args(NULL), _delimiter('\0') {}

virtual void execute(DCmdSource source, TRAPS);
virtual void print_help(const char* name) const;
virtual GrowableArray<const char*>* argument_name_array() const;
virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array() const;
virtual void parse(CmdLine* line, char delim, TRAPS);
protected:
virtual const char* javaClass() const = 0;
void invoke(JfrJavaArguments& method, TRAPS) const;
};

class JfrStartFlightRecordingDCmd : public JfrDCmd {
public:
JfrStartFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap) {}
JfrStartFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap, num_arguments()) {}

static const char* name() {
return "JFR.start";
Expand All @@ -72,7 +72,7 @@ class JfrStartFlightRecordingDCmd : public JfrDCmd {

class JfrDumpFlightRecordingDCmd : public JfrDCmd {
public:
JfrDumpFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap) {}
JfrDumpFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap, num_arguments()) {}

static const char* name() {
return "JFR.dump";
Expand All @@ -97,7 +97,7 @@ class JfrDumpFlightRecordingDCmd : public JfrDCmd {

class JfrCheckFlightRecordingDCmd : public JfrDCmd {
public:
JfrCheckFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap) {}
JfrCheckFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap, num_arguments()) {}

static const char* name() {
return "JFR.check";
Expand All @@ -122,7 +122,7 @@ class JfrCheckFlightRecordingDCmd : public JfrDCmd {

class JfrStopFlightRecordingDCmd : public JfrDCmd {
public:
JfrStopFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap) {}
JfrStopFlightRecordingDCmd(outputStream* output, bool heap) : JfrDCmd(output, heap, num_arguments()) {}

static const char* name() {
return "JFR.stop";
Expand Down

1 comment on commit f662127

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.