8319851: Improve exception logging
Reviewed-by: rhalade, matsaave, coleenp
This commit is contained in:
parent
0203c7e612
commit
8de2f6f883
src/hotspot/share
@ -2081,18 +2081,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 != nullptr) {
|
||||
return java_lang_String::as_symbol(detailed_message);
|
||||
}
|
||||
return nullptr;
|
||||
oop java_lang_Throwable::cause(oop throwable) {
|
||||
return throwable->obj_field(_cause_offset);
|
||||
}
|
||||
|
||||
void java_lang_Throwable::set_message(oop throwable, oop value) {
|
||||
|
@ -598,12 +598,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();
|
||||
|
@ -66,8 +66,8 @@ void ResolutionErrorTable::initialize() {
|
||||
|
||||
// create new error entry
|
||||
void ResolutionErrorTable::add_entry(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 != nullptr, "adding null obj");
|
||||
@ -97,26 +97,30 @@ ResolutionErrorEntry* ResolutionErrorTable::find_entry(const constantPoolHandle&
|
||||
return entry == nullptr ? nullptr : *entry;
|
||||
}
|
||||
|
||||
ResolutionErrorEntry::ResolutionErrorEntry(Symbol* error, Symbol* message,
|
||||
Symbol* cause, Symbol* cause_msg):
|
||||
ResolutionErrorEntry::ResolutionErrorEntry(Symbol* error, const char* message,
|
||||
Symbol* cause, const char* cause_msg):
|
||||
_error(error),
|
||||
_message(message),
|
||||
_message(message != nullptr ? os::strdup(message) : nullptr),
|
||||
_cause(cause),
|
||||
_cause_msg(cause_msg),
|
||||
_cause_msg(cause_msg != nullptr ? os::strdup(cause_msg) : nullptr),
|
||||
_nest_host_error(nullptr) {
|
||||
|
||||
Symbol::maybe_increment_refcount(_error);
|
||||
Symbol::maybe_increment_refcount(_message);
|
||||
Symbol::maybe_increment_refcount(_cause);
|
||||
Symbol::maybe_increment_refcount(_cause_msg);
|
||||
}
|
||||
|
||||
ResolutionErrorEntry::~ResolutionErrorEntry() {
|
||||
// decrement error refcount
|
||||
Symbol::maybe_decrement_refcount(_error);
|
||||
Symbol::maybe_decrement_refcount(_message);
|
||||
Symbol::maybe_decrement_refcount(_cause);
|
||||
Symbol::maybe_decrement_refcount(_cause_msg);
|
||||
|
||||
if (_message != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _message);
|
||||
}
|
||||
|
||||
if (_cause_msg != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _cause_msg);
|
||||
}
|
||||
|
||||
if (nest_host_error() != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, nest_host_error());
|
||||
|
@ -36,10 +36,11 @@ class ResolutionErrorTable : AllStatic {
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
static void add_entry(const constantPoolHandle& pool, int which, Symbol* error, Symbol* message,
|
||||
Symbol* cause, Symbol* cause_msg);
|
||||
static void add_entry(const constantPoolHandle& pool, int cp_index,
|
||||
Symbol* error, const char* error_msg,
|
||||
Symbol* cause, const char* cause_msg);
|
||||
|
||||
static void add_entry(const constantPoolHandle& pool, int which, const char* message);
|
||||
static void add_entry(const constantPoolHandle& pool, int cp_index, const char* message);
|
||||
|
||||
// find error given the constant pool and constant pool index
|
||||
static ResolutionErrorEntry* find_entry(const constantPoolHandle& pool, int cp_index);
|
||||
@ -68,34 +69,38 @@ public:
|
||||
class ResolutionErrorEntry : public CHeapObj<mtClass> {
|
||||
private:
|
||||
Symbol* _error;
|
||||
Symbol* _message;
|
||||
const char* _message;
|
||||
Symbol* _cause;
|
||||
Symbol* _cause_msg;
|
||||
const char* _cause_msg;
|
||||
const char* _nest_host_error;
|
||||
|
||||
NONCOPYABLE(ResolutionErrorEntry);
|
||||
|
||||
public:
|
||||
ResolutionErrorEntry(Symbol* error, Symbol* message, Symbol* cause, Symbol* cause_msg);
|
||||
// The incoming message and cause_msg are copied to the C-Heap.
|
||||
ResolutionErrorEntry(Symbol* error, const char* message,
|
||||
Symbol* cause, const char* cause_msg);
|
||||
|
||||
ResolutionErrorEntry(const char* message):
|
||||
// The incoming nest host error message is already in the C-Heap.
|
||||
ResolutionErrorEntry(const char* message):
|
||||
_error(nullptr),
|
||||
_message(nullptr),
|
||||
_cause(nullptr),
|
||||
_cause_msg(nullptr),
|
||||
_nest_host_error(message) {}
|
||||
|
||||
~ResolutionErrorEntry();
|
||||
~ResolutionErrorEntry();
|
||||
|
||||
void set_nest_host_error(const char* message) {
|
||||
_nest_host_error = message;
|
||||
}
|
||||
// The incoming nest host error message is already in the C-Heap.
|
||||
void set_nest_host_error(const char* message) {
|
||||
_nest_host_error = message;
|
||||
}
|
||||
|
||||
|
||||
Symbol* error() const { return _error; }
|
||||
Symbol* message() const { return _message; }
|
||||
const char* message() const { return _message; }
|
||||
Symbol* cause() const { return _cause; }
|
||||
Symbol* cause_msg() const { return _cause_msg; }
|
||||
const char* cause_msg() const { return _cause_msg; }
|
||||
const char* nest_host_error() const { return _nest_host_error; }
|
||||
};
|
||||
|
||||
|
@ -1799,8 +1799,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) {
|
||||
{
|
||||
MutexLocker ml(Thread::current(), SystemDictionary_lock);
|
||||
ResolutionErrorEntry* entry = ResolutionErrorTable::find_entry(pool, which);
|
||||
@ -1817,7 +1817,8 @@ 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) {
|
||||
|
||||
{
|
||||
MutexLocker ml(Thread::current(), SystemDictionary_lock);
|
||||
|
@ -272,12 +272,13 @@ public:
|
||||
|
||||
// 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 = nullptr, Symbol* cause_msg = nullptr);
|
||||
static void add_resolution_error(const constantPoolHandle& pool, int which,
|
||||
Symbol* error, const char* message,
|
||||
Symbol* cause = nullptr, const char* cause_msg = nullptr);
|
||||
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
|
||||
static void add_nest_host_error(const constantPoolHandle& pool, int which,
|
||||
|
@ -802,13 +802,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 != nullptr) {
|
||||
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:
|
||||
@ -831,49 +834,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 = nullptr;
|
||||
Symbol* cause_msg = nullptr;
|
||||
const char* cause_msg = nullptr;
|
||||
if (cause != nullptr && 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 = nullptr;
|
||||
const char* message = nullptr;
|
||||
Symbol* cause = nullptr;
|
||||
Symbol* cause_msg = nullptr;
|
||||
const char* cause_msg = nullptr;
|
||||
Symbol* error = SystemDictionary::find_resolution_error(this_cp, which, &message, &cause, &cause_msg);
|
||||
assert(error != nullptr, "checking");
|
||||
const char* cause_str = cause_msg != nullptr ? cause_msg->as_C_string() : nullptr;
|
||||
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
if (message != nullptr) {
|
||||
char* msg = message->as_C_string();
|
||||
if (cause != nullptr) {
|
||||
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 != nullptr) {
|
||||
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);
|
||||
@ -895,7 +897,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(cp_index).value() != error_tag) {
|
||||
add_resolution_error(this_cp, cp_index, tag, PENDING_EXCEPTION);
|
||||
add_resolution_error(THREAD, this_cp, cp_index, 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.
|
||||
|
@ -566,9 +566,9 @@ bool ConstantPoolCache::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);
|
||||
|
||||
int encoded_index = ResolutionErrorTable::encode_indy_index(
|
||||
ConstantPool::encode_invokedynamic_index(index));
|
||||
|
@ -566,11 +566,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());
|
||||
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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user