< prev index next >

src/share/vm/oops/constantPool.cpp

Print this page
rev 11945 : 8023697: failed class resolution reports different class name in detail message for the first and subsequent times
Summary: Cache detail message when we cache exception for constant pool resolution.
Reviewed-by: acorn, twisti, jrose
rev 11949 : 8048933: -XX:+TraceExceptions output should include the message
Summary: Add the exception detail message to the tracing output
Reviewed-by: minqi, dholmes
rev 11952 : Merge jdk8u272-b02

*** 233,250 **** } } // unlocking constantPool // The original attempt to resolve this constant pool entry failed so find the ! // original error and throw it again (JVMS 5.4.3). if (in_error) { ! Symbol* error = SystemDictionary::find_resolution_error(this_oop, which); ! guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table"); ! ResourceMark rm; ! // exception text will be the class name ! const char* className = this_oop->unresolved_klass_at(which)->as_C_string(); ! THROW_MSG_0(error, className); } if (do_resolve) { // this_oop must be unlocked during resolve_or_fail oop protection_domain = this_oop->pool_holder()->protection_domain(); --- 233,250 ---- } } // unlocking constantPool // The original attempt to resolve this constant pool entry failed so find the ! // class of the original error and throw another error of the same class (JVMS 5.4.3). ! // If there is a detail message, pass that detail message to the error constructor. ! // The JVMS does not strictly require us to duplicate the same detail message, ! // or any internal exception fields such as cause or stacktrace. But since the ! // detail message is often a class name or other literal string, we will repeat it if ! // we can find it in the symbol table. if (in_error) { ! throw_resolution_error(this_oop, which, CHECK_0); } if (do_resolve) { // this_oop must be unlocked during resolve_or_fail oop protection_domain = this_oop->pool_holder()->protection_domain();
*** 260,309 **** } // Failed to resolve class. We must record the errors so that subsequent attempts // to resolve this constant pool entry fail with the same error (JVMS 5.4.3). if (HAS_PENDING_EXCEPTION) { - ResourceMark rm; - Symbol* error = PENDING_EXCEPTION->klass()->name(); - - bool throw_orig_error = false; - { MonitorLockerEx ml(this_oop->lock()); // some other thread has beaten us and has resolved the class. if (this_oop->tag_at(which).is_klass()) { CLEAR_PENDING_EXCEPTION; entry = this_oop->resolved_klass_at(which); return entry.get_klass(); } ! if (!PENDING_EXCEPTION-> ! is_a(SystemDictionary::LinkageError_klass())) { ! // Just throw the exception and don't prevent these classes from ! // being loaded due to virtual machine errors like StackOverflow ! // 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_oop->tag_at(which).is_unresolved_klass_in_error()) { ! SystemDictionary::add_resolution_error(this_oop, which, error); ! this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError); ! } else { ! // some other thread has put the class in error state. ! error = SystemDictionary::find_resolution_error(this_oop, which); ! assert(error != NULL, "checking"); ! throw_orig_error = true; ! } ! } // unlocked ! ! if (throw_orig_error) { ! CLEAR_PENDING_EXCEPTION; ! ResourceMark rm; ! const char* className = this_oop->unresolved_klass_at(which)->as_C_string(); ! THROW_MSG_0(error, className); ! } ! ! return 0; } if (TraceClassResolution && !k()->oop_is_array()) { // skip resolving the constant pool so that this code get's // called the next time some bytecodes refer to this class. --- 260,281 ---- } // Failed to resolve class. We must record the errors so that subsequent attempts // to resolve this constant pool entry fail with the same error (JVMS 5.4.3). if (HAS_PENDING_EXCEPTION) { MonitorLockerEx ml(this_oop->lock()); // some other thread has beaten us and has resolved the class. if (this_oop->tag_at(which).is_klass()) { CLEAR_PENDING_EXCEPTION; entry = this_oop->resolved_klass_at(which); return entry.get_klass(); } ! // The tag could have changed to in-error before the lock but we have to ! // handle that here for the class case. ! save_and_throw_exception(this_oop, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0); } if (TraceClassResolution && !k()->oop_is_array()) { // skip resolving the constant pool so that this code get's // called the next time some bytecodes refer to this class.
*** 595,635 **** } // set_preresolution(); or some bit for future use return true; } ! // If resolution for MethodHandle or MethodType fails, save the exception // in the resolution error table, so that the same exception is thrown again. void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which, ! int tag, TRAPS) { ! ResourceMark rm; Symbol* error = PENDING_EXCEPTION->klass()->name(); - MonitorLockerEx ml(this_oop->lock()); // lock cpool to change tag. ! int error_tag = (tag == JVM_CONSTANT_MethodHandle) ? ! JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError; if (!PENDING_EXCEPTION-> is_a(SystemDictionary::LinkageError_klass())) { // Just throw the exception and don't prevent these classes from // being loaded due to virtual machine errors like StackOverflow // 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_oop->tag_at(which).value() != error_tag) { ! SystemDictionary::add_resolution_error(this_oop, which, error); this_oop->tag_at_put(which, error_tag); } else { ! // some other thread has put the class in error state. ! error = SystemDictionary::find_resolution_error(this_oop, which); ! assert(error != NULL, "checking"); ! CLEAR_PENDING_EXCEPTION; ! THROW_MSG(error, ""); } } // Called to resolve constants in the constant pool and return an oop. // Some constant pool entries cache their resolved oop. This is also // called to create oops from constants to use in arguments for invokedynamic oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) { oop result_oop = NULL; --- 567,643 ---- } // set_preresolution(); or some bit for future use return true; } ! Symbol* ConstantPool::exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception) { ! // Dig out the detailed message to reuse if possible ! Symbol* message = java_lang_Throwable::detail_message(pending_exception); ! if (message != NULL) { ! return message; ! } ! ! // Return specific message for the tag ! switch (tag.value()) { ! case JVM_CONSTANT_UnresolvedClass: ! // return the class name in the error message ! message = this_oop->unresolved_klass_at(which); ! break; ! case JVM_CONSTANT_MethodHandle: ! // return the method handle name in the error message ! message = this_oop->method_handle_name_ref_at(which); ! break; ! case JVM_CONSTANT_MethodType: ! // return the method type signature in the error message ! message = this_oop->method_type_signature_at(which); ! break; ! default: ! ShouldNotReachHere(); ! } ! ! return message; ! } ! ! void ConstantPool::throw_resolution_error(constantPoolHandle this_oop, int which, TRAPS) { ! Symbol* message = NULL; ! Symbol* error = SystemDictionary::find_resolution_error(this_oop, which, &message); ! assert(error != NULL && message != NULL, "checking"); ! CLEAR_PENDING_EXCEPTION; ! ResourceMark rm; ! THROW_MSG(error, message->as_C_string()); ! } ! ! // If resolution for Class, MethodHandle or MethodType fails, save the exception // in the resolution error table, so that the same exception is thrown again. void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which, ! constantTag tag, TRAPS) { ! assert(this_oop->lock()->is_locked(), "constant pool lock should be held"); Symbol* error = PENDING_EXCEPTION->klass()->name(); ! int error_tag = tag.error_value(); if (!PENDING_EXCEPTION-> is_a(SystemDictionary::LinkageError_klass())) { // Just throw the exception and don't prevent these classes from // being loaded due to virtual machine errors like StackOverflow // 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_oop->tag_at(which).value() != error_tag) { ! Symbol* message = exception_message(this_oop, which, tag, PENDING_EXCEPTION); ! SystemDictionary::add_resolution_error(this_oop, which, error, message); this_oop->tag_at_put(which, error_tag); } else { ! // some other thread put this in error state ! throw_resolution_error(this_oop, which, CHECK); } + + // This exits with some pending exception + assert(HAS_PENDING_EXCEPTION, "should not be cleared"); } + // Called to resolve constants in the constant pool and return an oop. // Some constant pool entries cache their resolved oop. This is also // called to create oops from constants to use in arguments for invokedynamic oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) { oop result_oop = NULL;
*** 653,665 **** index = this_oop->object_to_cp_index(cache_index); } jvalue prim_value; // temp used only in a few cases below ! int tag_value = this_oop->tag_at(index).value(); ! switch (tag_value) { case JVM_CONSTANT_UnresolvedClass: case JVM_CONSTANT_UnresolvedClassInError: case JVM_CONSTANT_Class: { --- 661,673 ---- index = this_oop->object_to_cp_index(cache_index); } jvalue prim_value; // temp used only in a few cases below ! constantTag tag = this_oop->tag_at(index); ! switch (tag.value()) { case JVM_CONSTANT_UnresolvedClass: case JVM_CONSTANT_UnresolvedClassInError: case JVM_CONSTANT_Class: {
*** 680,693 **** break; case JVM_CONSTANT_MethodHandleInError: case JVM_CONSTANT_MethodTypeInError: { ! Symbol* error = SystemDictionary::find_resolution_error(this_oop, index); ! guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table"); ! ResourceMark rm; ! THROW_MSG_0(error, ""); break; } case JVM_CONSTANT_MethodHandle: { --- 688,698 ---- break; case JVM_CONSTANT_MethodHandleInError: case JVM_CONSTANT_MethodTypeInError: { ! throw_resolution_error(this_oop, index, CHECK_NULL); break; } case JVM_CONSTANT_MethodHandle: {
*** 707,717 **** Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { ! save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL); } break; } case JVM_CONSTANT_MethodType: --- 712,723 ---- Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { ! MonitorLockerEx ml(this_oop->lock()); // lock cpool to change tag. ! save_and_throw_exception(this_oop, index, tag, CHECK_NULL); } break; } case JVM_CONSTANT_MethodType:
*** 723,733 **** signature->as_C_string()); KlassHandle klass(THREAD, this_oop->pool_holder()); Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { ! save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL); } break; } case JVM_CONSTANT_Integer: --- 729,740 ---- signature->as_C_string()); KlassHandle klass(THREAD, this_oop->pool_holder()); Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { ! MonitorLockerEx ml(this_oop->lock()); // lock cpool to change tag. ! save_and_throw_exception(this_oop, index, tag, CHECK_NULL); } break; } case JVM_CONSTANT_Integer:
*** 754,764 **** result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL); break; default: DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d", ! this_oop(), index, cache_index, tag_value) ); assert(false, "unexpected constant tag"); break; } if (cache_index >= 0) { --- 761,771 ---- result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL); break; default: DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d", ! this_oop(), index, cache_index, tag.value())); assert(false, "unexpected constant tag"); break; } if (cache_index >= 0) {
< prev index next >