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