< 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 >