Skip to content

Commit

Permalink
8319851: Improve exception logging
Browse files Browse the repository at this point in the history
Reviewed-by: mbaesken
Backport-of: 87dfeeb14fdd0fa1648a8bec91b5b713cc2c1b83
  • Loading branch information
martinuy authored and RealCLanger committed Apr 3, 2024
1 parent 07873cc commit 109e022
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 67 deletions.
29 changes: 16 additions & 13 deletions src/hotspot/share/classfile/javaClasses.cpp
Expand Up @@ -2076,18 +2076,17 @@ oop java_lang_Throwable::message(oop throwable) {
return throwable->obj_field(_detailMessage_offset);
}

oop java_lang_Throwable::cause(oop throwable) {
return throwable->obj_field(_cause_offset);
const char* java_lang_Throwable::message_as_utf8(oop throwable) {
oop msg = java_lang_Throwable::message(throwable);
const char* msg_utf8 = nullptr;
if (msg != nullptr) {
msg_utf8 = java_lang_String::as_utf8_string(msg);
}
return msg_utf8;
}

// Return Symbol for detailed_message or NULL
Symbol* java_lang_Throwable::detail_message(oop throwable) {
PreserveExceptionMark pm(Thread::current());
oop detailed_message = java_lang_Throwable::message(throwable);
if (detailed_message != NULL) {
return java_lang_String::as_symbol(detailed_message);
}
return NULL;
oop java_lang_Throwable::cause(oop throwable) {
return throwable->obj_field(_cause_offset);
}

void java_lang_Throwable::set_message(oop throwable, oop value) {
Expand Down Expand Up @@ -2739,15 +2738,19 @@ Handle java_lang_Throwable::create_initialization_error(JavaThread* current, Han
assert(throwable.not_null(), "shouldn't be");

// Now create the message from the original exception and thread name.
Symbol* message = java_lang_Throwable::detail_message(throwable());
ResourceMark rm(current);
stringStream st;
const char *message = nullptr;
oop detailed_message = java_lang_Throwable::message(throwable());
if (detailed_message != nullptr) {
message = java_lang_String::as_utf8_string(detailed_message);
}
st.print("Exception %s%s ", throwable()->klass()->name()->as_klass_external_name(),
message == nullptr ? "" : ":");
if (message == NULL) {
if (message == nullptr) {
st.print("[in thread \"%s\"]", current->name());
} else {
st.print("%s [in thread \"%s\"]", message->as_C_string(), current->name());
st.print("%s [in thread \"%s\"]", message, current->name());
}

Symbol* exception_name = vmSymbols::java_lang_ExceptionInInitializerError();
Expand Down
8 changes: 5 additions & 3 deletions src/hotspot/share/classfile/javaClasses.hpp
Expand Up @@ -549,12 +549,14 @@ class java_lang_Throwable: AllStatic {
static void set_backtrace(oop throwable, oop value);
static int depth(oop throwable);
static void set_depth(oop throwable, int value);
static int get_detailMessage_offset() { CHECK_INIT(_detailMessage_offset); }
// Message
static int get_detailMessage_offset() { CHECK_INIT(_detailMessage_offset); }
static oop message(oop throwable);
static oop cause(oop throwable);
static const char* message_as_utf8(oop throwable);
static void set_message(oop throwable, oop value);
static Symbol* detail_message(oop throwable);

static oop cause(oop throwable);

static void print_stack_element(outputStream *st, Method* method, int bci);

static void compute_offsets();
Expand Down
23 changes: 9 additions & 14 deletions src/hotspot/share/classfile/resolutionErrors.cpp
Expand Up @@ -36,8 +36,8 @@
// create new error entry
void ResolutionErrorTable::add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index,
Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg)
Symbol* error, const char* message,
Symbol* cause, const char* cause_msg)
{
assert_locked_or_safepoint(SystemDictionary_lock);
assert(!pool.is_null() && error != NULL, "adding NULL obj");
Expand Down Expand Up @@ -95,11 +95,8 @@ void ResolutionErrorEntry::set_error(Symbol* e) {
}
}

void ResolutionErrorEntry::set_message(Symbol* c) {
_message = c;
if (_message != NULL) {
_message->increment_refcount();
}
void ResolutionErrorEntry::set_message(const char* c) {
_message = c != nullptr ? os::strdup(c) : nullptr;
}

void ResolutionErrorEntry::set_cause(Symbol* c) {
Expand All @@ -109,13 +106,11 @@ void ResolutionErrorEntry::set_cause(Symbol* c) {
}
}

void ResolutionErrorEntry::set_cause_msg(Symbol* c) {
_cause_msg = c;
if (_cause_msg != NULL) {
_cause_msg->increment_refcount();
}
void ResolutionErrorEntry::set_cause_msg(const char* c) {
_cause_msg = c != nullptr ? os::strdup(c) : nullptr;
}

// The incoming nest host error message is already in the C-Heap.
void ResolutionErrorEntry::set_nest_host_error(const char* message) {
_nest_host_error = message;
}
Expand All @@ -126,13 +121,13 @@ void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
entry->error()->decrement_refcount();
}
if (entry->message() != NULL) {
entry->message()->decrement_refcount();
FREE_C_HEAP_ARRAY(char, entry->message());
}
if (entry->cause() != NULL) {
entry->cause()->decrement_refcount();
}
if (entry->cause_msg() != NULL) {
entry->cause_msg()->decrement_refcount();
FREE_C_HEAP_ARRAY(char, entry->cause_msg());
}
if (entry->nest_host_error() != NULL) {
FREE_C_HEAP_ARRAY(char, entry->nest_host_error());
Expand Down
21 changes: 12 additions & 9 deletions src/hotspot/share/classfile/resolutionErrors.hpp
Expand Up @@ -61,11 +61,11 @@ class ResolutionErrorTable : public Hashtable<ConstantPool*, mtClass> {
}

void add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int which, Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg);
const constantPoolHandle& pool, int cp_index, Symbol* error, const char* error_msg,
Symbol* cause, const char* cause_msg);

void add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int which, const char* message);
const constantPoolHandle& pool, int cp_index, const char* message);

// find error given the constant pool and constant pool index
ResolutionErrorEntry* find_entry(int index, unsigned int hash,
Expand Down Expand Up @@ -96,9 +96,9 @@ class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
private:
int _cp_index;
Symbol* _error;
Symbol* _message;
const char* _message;
Symbol* _cause;
Symbol* _cause_msg;
const char* _cause_msg;
const char* _nest_host_error;

public:
Expand All @@ -110,16 +110,19 @@ class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
Symbol* error() const { return _error; }
void set_error(Symbol* e);

Symbol* message() const { return _message; }
void set_message(Symbol* c);
const char* message() const { return _message; }
// The incoming message is copied to the C-Heap.
void set_message(const char* c);

Symbol* cause() const { return _cause; }
void set_cause(Symbol* c);

Symbol* cause_msg() const { return _cause_msg; }
void set_cause_msg(Symbol* c);
const char* cause_msg() const { return _cause_msg; }
// The incoming cause_msg is copied to the C-Heap.
void set_cause_msg(const char* c);

const char* nest_host_error() const { return _nest_host_error; }
// The incoming nest host error message is already in the C-Heap.
void set_nest_host_error(const char* message);

ResolutionErrorEntry* next() const {
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/classfile/systemDictionary.cpp
Expand Up @@ -1846,8 +1846,8 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
// Add entry to resolution error table to record the error when the first
// attempt to resolve a reference to a class has failed.
void SystemDictionary::add_resolution_error(const constantPoolHandle& pool, int which,
Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg) {
Symbol* error, const char* message,
Symbol* cause, const char* cause_msg) {
unsigned int hash = resolution_errors()->compute_hash(pool, which);
int index = resolution_errors()->hash_to_index(hash);
{
Expand All @@ -1866,7 +1866,7 @@ void SystemDictionary::delete_resolution_error(ConstantPool* pool) {

// Lookup resolution error table. Returns error if found, otherwise NULL.
Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool, int which,
Symbol** message, Symbol** cause, Symbol** cause_msg) {
const char** message, Symbol** cause, const char** cause_msg) {
unsigned int hash = resolution_errors()->compute_hash(pool, which);
int index = resolution_errors()->hash_to_index(hash);
{
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/classfile/systemDictionary.hpp
Expand Up @@ -281,10 +281,10 @@ class SystemDictionary : AllStatic {
// Record the error when the first attempt to resolve a reference from a constant
// pool entry to a class fails.
static void add_resolution_error(const constantPoolHandle& pool, int which, Symbol* error,
Symbol* message, Symbol* cause = NULL, Symbol* cause_msg = NULL);
const char* message, Symbol* cause = NULL, const char* cause_msg = NULL);
static void delete_resolution_error(ConstantPool* pool);
static Symbol* find_resolution_error(const constantPoolHandle& pool, int which,
Symbol** message, Symbol** cause, Symbol** cause_msg);
const char** message, Symbol** cause, const char** cause_msg);


// Record a nest host resolution/validation error
Expand Down
38 changes: 20 additions & 18 deletions src/hotspot/share/oops/constantPool.cpp
Expand Up @@ -767,13 +767,16 @@ void ConstantPool::resolve_string_constants_impl(const constantPoolHandle& this_
}
}

static Symbol* exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception) {
static const char* exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception) {
// Note: caller needs ResourceMark

// Dig out the detailed message to reuse if possible
Symbol* message = java_lang_Throwable::detail_message(pending_exception);
if (message != NULL) {
return message;
const char* msg = java_lang_Throwable::message_as_utf8(pending_exception);
if (msg != nullptr) {
return msg;
}

Symbol* message = nullptr;
// Return specific message for the tag
switch (tag.value()) {
case JVM_CONSTANT_UnresolvedClass:
Expand All @@ -796,49 +799,48 @@ static Symbol* exception_message(const constantPoolHandle& this_cp, int which, c
ShouldNotReachHere();
}

return message;
return message != nullptr ? message->as_C_string() : nullptr;
}

static void add_resolution_error(const constantPoolHandle& this_cp, int which,
static void add_resolution_error(JavaThread* current, const constantPoolHandle& this_cp, int which,
constantTag tag, oop pending_exception) {
ResourceMark rm(current);

Symbol* error = pending_exception->klass()->name();
oop cause = java_lang_Throwable::cause(pending_exception);

// Also dig out the exception cause, if present.
Symbol* cause_sym = NULL;
Symbol* cause_msg = NULL;
const char* cause_msg = nullptr;
if (cause != NULL && cause != pending_exception) {
cause_sym = cause->klass()->name();
cause_msg = java_lang_Throwable::detail_message(cause);
cause_msg = java_lang_Throwable::message_as_utf8(cause);
}

Symbol* message = exception_message(this_cp, which, tag, pending_exception);
const char* message = exception_message(this_cp, which, tag, pending_exception);
SystemDictionary::add_resolution_error(this_cp, which, error, message, cause_sym, cause_msg);
}


void ConstantPool::throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS) {
ResourceMark rm(THREAD);
Symbol* message = NULL;
const char* message = NULL;
Symbol* cause = NULL;
Symbol* cause_msg = NULL;
const char* cause_msg = NULL;
Symbol* error = SystemDictionary::find_resolution_error(this_cp, which, &message, &cause, &cause_msg);
assert(error != NULL, "checking");
const char* cause_str = cause_msg != NULL ? cause_msg->as_C_string() : NULL;

CLEAR_PENDING_EXCEPTION;
if (message != NULL) {
char* msg = message->as_C_string();
if (cause != NULL) {
Handle h_cause = Exceptions::new_exception(THREAD, cause, cause_str);
THROW_MSG_CAUSE(error, msg, h_cause);
Handle h_cause = Exceptions::new_exception(THREAD, cause, cause_msg);
THROW_MSG_CAUSE(error, message, h_cause);
} else {
THROW_MSG(error, msg);
THROW_MSG(error, message);
}
} else {
if (cause != NULL) {
Handle h_cause = Exceptions::new_exception(THREAD, cause, cause_str);
Handle h_cause = Exceptions::new_exception(THREAD, cause, cause_msg);
THROW_CAUSE(error, h_cause);
} else {
THROW(error);
Expand All @@ -860,7 +862,7 @@ void ConstantPool::save_and_throw_exception(const constantPoolHandle& this_cp, i
// and OutOfMemoryError, etc, or if the thread was hit by stop()
// Needs clarification to section 5.4.3 of the VM spec (see 6308271)
} else if (this_cp->tag_at(which).value() != error_tag) {
add_resolution_error(this_cp, which, tag, PENDING_EXCEPTION);
add_resolution_error(THREAD, this_cp, which, tag, PENDING_EXCEPTION);
// CAS in the tag. If a thread beat us to registering this error that's fine.
// If another thread resolved the reference, this is a race condition. This
// thread may have had a security manager or something temporary.
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/oops/cpCache.cpp
Expand Up @@ -497,9 +497,9 @@ bool ConstantPoolCacheEntry::save_and_throw_indy_exc(
CLEAR_PENDING_EXCEPTION;
return false;
}

ResourceMark rm(THREAD);
Symbol* error = PENDING_EXCEPTION->klass()->name();
Symbol* message = java_lang_Throwable::detail_message(PENDING_EXCEPTION);
const char* message = java_lang_Throwable::message_as_utf8(PENDING_EXCEPTION);

SystemDictionary::add_resolution_error(cpool, index, error, message);
set_indy_resolution_failed();
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/utilities/exceptions.cpp
Expand Up @@ -563,11 +563,11 @@ void Exceptions::debug_check_abort_helper(Handle exception, const char* message)
// for logging exceptions
void Exceptions::log_exception(Handle exception, const char* message) {
ResourceMark rm;
Symbol* detail_message = java_lang_Throwable::detail_message(exception());
if (detail_message != NULL) {
const char* detail_message = java_lang_Throwable::message_as_utf8(exception());
if (detail_message != nullptr) {
log_info(exceptions)("Exception <%s: %s>\n thrown in %s",
exception->print_value_string(),
detail_message->as_C_string(),
detail_message,
message);
} else {
log_info(exceptions)("Exception <%s>\n thrown in %s",
Expand Down

0 comments on commit 109e022

Please sign in to comment.