< prev index next >
src/hotspot/share/oops/instanceKlass.cpp
Print this page
rev 50339 : 8203824: Chain exception from initialization in later NoClassDefFoundErrors.
*** 511,530 ****
bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
if (DumpSharedSpaces && is_in_error_state()) {
// This is for CDS dumping phase only -- we use the in_error_state to indicate that
// the class has failed verification. Throwing the NoClassDefFoundError here is just
! // a convenient way to stop repeat attempts to verify the same (bad) class.
//
// Note that the NoClassDefFoundError is not part of the JLS, and should not be thrown
// if we are executing Java code. This is not a problem for CDS dumping phase since
// it doesn't execute any Java code.
ResourceMark rm(THREAD);
! Exceptions::fthrow(THREAD_AND_LOCATION,
vmSymbols::java_lang_NoClassDefFoundError(),
! "Class %s, or one of its supertypes, failed class initialization",
! external_name());
return false;
}
// return if already verified
if (is_linked()) {
return true;
--- 511,534 ----
bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
if (DumpSharedSpaces && is_in_error_state()) {
// This is for CDS dumping phase only -- we use the in_error_state to indicate that
// the class has failed verification. Throwing the NoClassDefFoundError here is just
! // a convenient way to stop repeated attempts to verify the same (bad) class.
//
// Note that the NoClassDefFoundError is not part of the JLS, and should not be thrown
// if we are executing Java code. This is not a problem for CDS dumping phase since
// it doesn't execute any Java code.
ResourceMark rm(THREAD);
! stringStream ss;
! ss.print("%s: cannot link class because prior initialization attempt failed",
! class_loader_and_module_name());
! // Chain the exception that originally caused clinit to fail.
! Exceptions::_throw_msg_cause(THREAD_AND_LOCATION,
vmSymbols::java_lang_NoClassDefFoundError(),
! ss.as_string(),
! Handle(THREAD, java_lang_Class::exceptionThrownDuringClinit(java_mirror())));
return false;
}
// return if already verified
if (is_linked()) {
return true;
*** 689,698 ****
--- 693,711 ----
ik->initialize(CHECK);
}
}
}
+ // Store exception h_exception thrown during clinit to the corresponding field of the
+ // class that could not be initialized by calling the appropriate java method.
+ static void set_exception_thrown_during_clinit(Handle h_mirror, Handle h_exception, TRAPS) {
+ JavaValue result(T_VOID);
+ JavaCalls::call_virtual(&result, h_mirror, h_mirror->klass(),
+ vmSymbols::setExceptionThrownDuringClinit_name(),
+ vmSymbols::throwable_void_signature(), h_exception, CHECK);
+ }
+
void InstanceKlass::initialize_impl(TRAPS) {
HandleMark hm(THREAD);
// Make sure klass is linked (verified) before initialization
// A class could already be verified, since it has been reflected upon.
*** 733,753 ****
// Step 5
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);
! } else {
! jio_snprintf(message, msglen, "%s%s", desc, className);
! THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
! }
}
// Step 6
set_init_state(being_initialized);
set_init_thread(self);
--- 746,764 ----
// Step 5
if (is_in_error_state()) {
DTRACE_CLASSINIT_PROBE_WAIT(erroneous, -1, wait);
ResourceMark rm(THREAD);
! stringStream ss;
! ss.print("%s: cannot initialize class because prior initialization attempt failed",
! class_loader_and_module_name());
! // Chain the exception that originally caused clinit to fail.
! Exceptions::_throw_msg_cause(THREAD_AND_LOCATION,
! vmSymbols::java_lang_NoClassDefFoundError(),
! ss.as_string(),
! Handle(THREAD, java_lang_Class::exceptionThrownDuringClinit(java_mirror())));
! return;
}
// Step 6
set_init_state(being_initialized);
set_init_thread(self);
*** 773,792 ****
if (HAS_PENDING_EXCEPTION) {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
// Locks object, set state, and notify all waiting threads
set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION;
}
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, -1, wait);
THROW_OOP(e());
}
}
-
// Look for aot compiled methods for this klass, including class initializer.
AOTLoader::load_for_klass(this, THREAD);
// Step 8
{
--- 784,805 ----
if (HAS_PENDING_EXCEPTION) {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
+ // Store the exception that originally caused clinit to fail so it can be
+ // chained in later NoClassDefFoundErrors.
+ set_exception_thrown_during_clinit(Handle(THREAD, java_mirror()), e, THREAD);
// Locks object, set state, and notify all waiting threads
set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION;
}
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, -1, wait);
THROW_OOP(e());
}
}
// Look for aot compiled methods for this klass, including class initializer.
AOTLoader::load_for_klass(this, THREAD);
// Step 8
{
*** 818,847 ****
// JVMTI has already reported the pending exception
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
{
EXCEPTION_MARK;
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
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
}
DTRACE_CLASSINIT_PROBE_WAIT(error, -1, wait);
- if (e->is_a(SystemDictionary::Error_klass())) {
THROW_OOP(e());
- } else {
- JavaCallArguments args(e);
- THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),
- vmSymbols::throwable_void_signature(),
- &args);
- }
}
DTRACE_CLASSINIT_PROBE_WAIT(end, -1, wait);
}
-
void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) {
Handle h_init_lock(THREAD, init_lock());
if (h_init_lock() != NULL) {
ObjectLocker ol(h_init_lock, THREAD);
set_init_state(state);
--- 831,877 ----
// JVMTI has already reported the pending exception
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
{
EXCEPTION_MARK;
+ // Wrap anything but errors into ExceptionInInitializerError.
+ if (!e->is_a(SystemDictionary::Error_klass())) {
+ JavaCallArguments args(e);
+ Handle h_loader(THREAD, NULL);
+ Handle h_prot(THREAD, NULL);
+ Handle h_cause(THREAD, NULL);
+ e = Exceptions::new_exception(THREAD, vmSymbols::java_lang_ExceptionInInitializerError(),
+ vmSymbols::throwable_void_signature(), &args, h_cause, h_loader, h_prot);
+ // If we failed to wrap, something like an OOM must have
+ // occurred - just pass that on. The previous code does the
+ // wrapping after the CLEAR_PENDING_EXCEPTION below (with
+ // identical effect for the user), but we want to store the
+ // wrapped exception as exception_thrown_during_clinit, so we
+ // must wrap it here. In fact, whatever is thrown during
+ // wrapping (Error or RuntimeException) is passed on to the
+ // caller.
+ if (HAS_PENDING_EXCEPTION) {
+ e = Handle(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION; // Ignore any exception thrown, e is thrown below.
+ }
+ }
+
+ // Store the exception that originally caused clinit to fail so it can be
+ // chained in later NoClassDefFoundErrors.
+ set_exception_thrown_during_clinit(Handle(THREAD, java_mirror()), e, THREAD);
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
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
}
DTRACE_CLASSINIT_PROBE_WAIT(error, -1, wait);
THROW_OOP(e());
}
DTRACE_CLASSINIT_PROBE_WAIT(end, -1, wait);
}
void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) {
Handle h_init_lock(THREAD, init_lock());
if (h_init_lock() != NULL) {
ObjectLocker ol(h_init_lock, THREAD);
set_init_state(state);
< prev index next >