mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8048190: NoClassDefFoundError omits original ExceptionInInitializerError
Reviewed-by: dholmes, iklam
This commit is contained in:
parent
7e14c3cc11
commit
464e874a5c
9 changed files with 255 additions and 13 deletions
|
@ -1015,6 +1015,54 @@ void InstanceKlass::initialize_super_interfaces(TRAPS) {
|
|||
}
|
||||
}
|
||||
|
||||
ResourceHashtable<const InstanceKlass*, OopHandle, 107, ResourceObj::C_HEAP, mtClass>
|
||||
_initialization_error_table;
|
||||
|
||||
void InstanceKlass::add_initialization_error(JavaThread* current, Handle exception) {
|
||||
// Create the same exception with a message indicating the thread name,
|
||||
// and the StackTraceElements.
|
||||
// If the initialization error is OOM, this might not work, but if GC kicks in
|
||||
// this would be still be helpful.
|
||||
JavaThread* THREAD = current;
|
||||
Handle cause = java_lang_Throwable::get_cause_with_stack_trace(exception, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION || cause.is_null()) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLocker ml(THREAD, ClassInitError_lock);
|
||||
OopHandle elem = OopHandle(Universe::vm_global(), cause());
|
||||
bool created = false;
|
||||
_initialization_error_table.put_if_absent(this, elem, &created);
|
||||
assert(created, "Initialization is single threaded");
|
||||
ResourceMark rm(THREAD);
|
||||
log_trace(class, init)("Initialization error added for class %s", external_name());
|
||||
}
|
||||
|
||||
oop InstanceKlass::get_initialization_error(JavaThread* current) {
|
||||
MutexLocker ml(current, ClassInitError_lock);
|
||||
OopHandle* h = _initialization_error_table.get(this);
|
||||
return (h != nullptr) ? h->resolve() : nullptr;
|
||||
}
|
||||
|
||||
// Need to remove entries for unloaded classes.
|
||||
void InstanceKlass::clean_initialization_error_table() {
|
||||
struct InitErrorTableCleaner {
|
||||
bool do_entry(const InstanceKlass* ik, OopHandle h) {
|
||||
if (!ik->is_loader_alive()) {
|
||||
h.release(Universe::vm_global());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MutexLocker ml(ClassInitError_lock);
|
||||
InitErrorTableCleaner cleaner;
|
||||
_initialization_error_table.unlink(&cleaner);
|
||||
}
|
||||
|
||||
void InstanceKlass::initialize_impl(TRAPS) {
|
||||
HandleMark hm(THREAD);
|
||||
|
||||
|
@ -1061,16 +1109,15 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|||
if (is_in_error_state()) {
|
||||
DTRACE_CLASSINIT_PROBE_WAIT(erroneous, -1, wait);
|
||||
ResourceMark rm(THREAD);
|
||||
const char* desc = "Could not initialize class ";
|
||||
const char* className = external_name();
|
||||
size_t msglen = strlen(desc) + strlen(className) + 1;
|
||||
char* message = NEW_RESOURCE_ARRAY(char, msglen);
|
||||
if (NULL == message) {
|
||||
// Out of memory: can't create detailed error message
|
||||
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
|
||||
Handle cause(THREAD, get_initialization_error(THREAD));
|
||||
|
||||
stringStream ss;
|
||||
ss.print("Could not initialize class %s", external_name());
|
||||
if (cause.is_null()) {
|
||||
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), ss.as_string());
|
||||
} else {
|
||||
jio_snprintf(message, msglen, "%s%s", desc, className);
|
||||
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
|
||||
THROW_MSG_CAUSE(vmSymbols::java_lang_NoClassDefFoundError(),
|
||||
ss.as_string(), cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1101,6 +1148,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|||
CLEAR_PENDING_EXCEPTION;
|
||||
{
|
||||
EXCEPTION_MARK;
|
||||
add_initialization_error(THREAD, e);
|
||||
// Locks object, set state, and notify all waiting threads
|
||||
set_initialization_state_and_notify(initialization_error, THREAD);
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
|
@ -1136,9 +1184,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|||
// Step 9
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
set_initialization_state_and_notify(fully_initialized, CHECK);
|
||||
{
|
||||
debug_only(vtable().verify(tty, true);)
|
||||
}
|
||||
debug_only(vtable().verify(tty, true);)
|
||||
}
|
||||
else {
|
||||
// Step 10 and 11
|
||||
|
@ -1149,6 +1195,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|||
JvmtiExport::clear_detected_exception(jt);
|
||||
{
|
||||
EXCEPTION_MARK;
|
||||
add_initialization_error(THREAD, e);
|
||||
set_initialization_state_and_notify(initialization_error, THREAD);
|
||||
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below
|
||||
// JVMTI has already reported the pending exception
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue