mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8221470: Print methods in exception messages in java-like Syntax
Reviewed-by: dholmes, mdoerr, coleenp
This commit is contained in:
parent
6780d21dd6
commit
39f3368ffd
22 changed files with 470 additions and 161 deletions
|
@ -2060,7 +2060,9 @@ void ClassVerifier::class_format_error(const char* msg, ...) {
|
|||
ss.vprint(msg, va);
|
||||
va_end(va);
|
||||
if (!_method.is_null()) {
|
||||
ss.print(" in method %s", _method->name_and_sig_as_C_string());
|
||||
ss.print(" in method '");
|
||||
_method->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
}
|
||||
_message = ss.as_string();
|
||||
}
|
||||
|
|
|
@ -264,10 +264,6 @@ LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) {
|
|||
_check_access = true;
|
||||
}
|
||||
|
||||
char* LinkInfo::method_string() const {
|
||||
return Method::name_and_sig_as_C_string(_resolved_klass, _name, _signature);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void LinkInfo::print() {
|
||||
ResourceMark rm;
|
||||
|
@ -593,14 +589,12 @@ void LinkResolver::check_method_accessability(Klass* ref_klass,
|
|||
Exceptions::fthrow(
|
||||
THREAD_AND_LOCATION,
|
||||
vmSymbols::java_lang_IllegalAccessError(),
|
||||
"class %s tried to access %s%s%smethod %s.%s%s (%s%s%s)",
|
||||
"class %s tried to access %s%s%smethod '%s' (%s%s%s)",
|
||||
ref_klass->external_name(),
|
||||
sel_method->is_abstract() ? "abstract " : "",
|
||||
sel_method->is_protected() ? "protected " : "",
|
||||
sel_method->is_private() ? "private " : "",
|
||||
sel_klass->external_name(),
|
||||
sel_method->name()->as_C_string(),
|
||||
sel_method->signature()->as_C_string(),
|
||||
sel_method->external_name(),
|
||||
(same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
|
||||
(same_module) ? "" : "; ",
|
||||
(same_module) ? "" : sel_klass->class_in_module_of_loader()
|
||||
|
@ -670,12 +664,11 @@ void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info,
|
|||
assert(target_loader_data != NULL, "resolved method's class has no class loader data");
|
||||
|
||||
stringStream ss;
|
||||
ss.print("loader constraint violation: when resolving %s"
|
||||
" \"%s\" the class loader %s of the current class, %s,"
|
||||
ss.print("loader constraint violation: when resolving %s '", method_type);
|
||||
Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature());
|
||||
ss.print("' the class loader %s of the current class, %s,"
|
||||
" and the class loader %s for the method's defining class, %s, have"
|
||||
" different Class objects for the type %s used in the signature (%s; %s)",
|
||||
method_type,
|
||||
link_info.method_string(),
|
||||
current_loader_data->loader_name_and_id(),
|
||||
current_class->name()->as_C_string(),
|
||||
target_loader_data->loader_name_and_id(),
|
||||
|
@ -739,9 +732,11 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
|
|||
// 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref
|
||||
if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Method %s must be Methodref constant", link_info.method_string());
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Method '");
|
||||
Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature());
|
||||
ss.print("' must be Methodref constant");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
// 3. lookup method in resolved klass and its super klasses
|
||||
|
@ -764,11 +759,12 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
|
|||
// 5. method lookup failed
|
||||
if (resolved_method.is_null()) {
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
Method::print_external_name(&ss, resolved_klass, link_info.name(), link_info.signature());
|
||||
ss.print("'");
|
||||
THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(),
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
link_info.name(),
|
||||
link_info.signature()),
|
||||
nested_exception, NULL);
|
||||
ss.as_string(), nested_exception, NULL);
|
||||
}
|
||||
|
||||
// 6. access checks, access checking may be turned off when calling from within the VM.
|
||||
|
@ -840,9 +836,11 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B
|
|||
// check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref
|
||||
if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Method %s must be InterfaceMethodref constant", link_info.method_string());
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Method '");
|
||||
Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature());
|
||||
ss.print("' must be InterfaceMethodref constant");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
// lookup method in this interface or its super, java.lang.Object
|
||||
|
@ -857,10 +855,11 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B
|
|||
if (resolved_method.is_null()) {
|
||||
// no method found
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(),
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
link_info.name(),
|
||||
link_info.signature()));
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
Method::print_external_name(&ss, resolved_klass, link_info.name(), link_info.signature());
|
||||
ss.print("'");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string());
|
||||
}
|
||||
|
||||
if (link_info.check_access()) {
|
||||
|
@ -881,11 +880,12 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B
|
|||
|
||||
if (code != Bytecodes::_invokestatic && resolved_method->is_static()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s",
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(), resolved_method->signature()));
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Expected instance not static method '");
|
||||
Method::print_external_name(&ss, resolved_klass,
|
||||
resolved_method->name(), resolved_method->signature());
|
||||
ss.print("'");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
if (log_develop_is_enabled(Trace, itables)) {
|
||||
|
@ -1086,11 +1086,11 @@ methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_i
|
|||
// check if static
|
||||
if (!resolved_method->is_static()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()));
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Expected static method '");
|
||||
resolved_method()->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
return resolved_method;
|
||||
}
|
||||
|
@ -1127,14 +1127,16 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_
|
|||
if (resolved_method->name() == vmSymbols::object_initializer_name() &&
|
||||
resolved_method->method_holder() != resolved_klass) {
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream ss;
|
||||
ss.print("%s: method '", resolved_klass->external_name());
|
||||
resolved_method->signature()->print_as_signature_external_return_type(&ss);
|
||||
ss.print(" %s(", resolved_method->name()->as_C_string());
|
||||
resolved_method->signature()->print_as_signature_external_parameters(&ss);
|
||||
ss.print(")' not found");
|
||||
Exceptions::fthrow(
|
||||
THREAD_AND_LOCATION,
|
||||
vmSymbols::java_lang_NoSuchMethodError(),
|
||||
"%s: method %s%s not found",
|
||||
resolved_klass->external_name(),
|
||||
resolved_method->name()->as_C_string(),
|
||||
resolved_method->signature()->as_C_string()
|
||||
);
|
||||
"%s", ss.as_string());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1153,27 +1155,23 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_
|
|||
if (!is_reflect &&
|
||||
!klass_to_check->is_same_or_direct_interface(resolved_klass)) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf),
|
||||
"Interface method reference: %s, is in an indirect superinterface of %s",
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()),
|
||||
current_klass->external_name());
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Interface method reference: '");
|
||||
resolved_method->print_external_name(&ss);
|
||||
ss.print("', is in an indirect superinterface of %s",
|
||||
current_klass->external_name());
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
}
|
||||
|
||||
// check if not static
|
||||
if (resolved_method->is_static()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf),
|
||||
"Expecting non-static method %s",
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()));
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Expecting non-static method '");
|
||||
resolved_method->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
if (log_develop_is_enabled(Trace, itables)) {
|
||||
|
@ -1219,10 +1217,11 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result,
|
|||
// check if found
|
||||
if (sel_method.is_null()) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()));
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
resolved_method->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
|
||||
// check loader constraints if found a different method
|
||||
} else if (sel_method() != resolved_method()) {
|
||||
check_method_loader_constraints(link_info, sel_method, "method", CHECK);
|
||||
|
@ -1244,8 +1243,8 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result,
|
|||
char buf[500];
|
||||
jio_snprintf(buf, sizeof(buf),
|
||||
"Receiver class %s must be the current class or a subtype of interface %s",
|
||||
receiver_klass->name()->as_C_string(),
|
||||
sender->name()->as_C_string());
|
||||
receiver_klass->external_name(),
|
||||
sender->external_name());
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), buf);
|
||||
}
|
||||
}
|
||||
|
@ -1254,20 +1253,21 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result,
|
|||
// check if not static
|
||||
if (sel_method->is_static()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()));
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Expecting non-static method '");
|
||||
resolved_method->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
// check if abstract
|
||||
if (sel_method->is_abstract()) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
sel_method->name(),
|
||||
sel_method->signature()));
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
Method::print_external_name(&ss, resolved_klass, sel_method->name(), sel_method->signature());
|
||||
ss.print("'");
|
||||
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
|
||||
}
|
||||
|
||||
if (log_develop_is_enabled(Trace, itables)) {
|
||||
|
@ -1305,23 +1305,22 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_
|
|||
// This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method
|
||||
if (resolved_klass->is_interface() && resolved_method->is_private()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s",
|
||||
Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()),
|
||||
(current_klass == NULL ? "<NULL>" : current_klass->internal_name()));
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("private interface method requires invokespecial, not invokevirtual: method '");
|
||||
resolved_method->print_external_name(&ss);
|
||||
ss.print("', caller-class: %s",
|
||||
(current_klass == NULL ? "<null>" : current_klass->internal_name()));
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
// check if not static
|
||||
if (resolved_method->is_static()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass,
|
||||
resolved_method->name(),
|
||||
resolved_method->signature()));
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Expecting non-static method '");
|
||||
resolved_method->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
if (log_develop_is_enabled(Trace, vtables)) {
|
||||
|
@ -1470,10 +1469,11 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result,
|
|||
// Throw Illegal Access Error if selected_method is not public.
|
||||
if (!selected_method->is_public()) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
|
||||
Method::name_and_sig_as_C_string(recv_klass,
|
||||
selected_method->name(),
|
||||
selected_method->signature()));
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
Method::print_external_name(&ss, recv_klass, selected_method->name(), selected_method->signature());
|
||||
ss.print("'");
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
|
||||
}
|
||||
// check if abstract
|
||||
if (check_null_and_abstract && selected_method->is_abstract()) {
|
||||
|
@ -1806,19 +1806,22 @@ void LinkResolver::throw_abstract_method_error(const methodHandle& resolved_meth
|
|||
}
|
||||
|
||||
assert(resolved_method.not_null(), "Sanity");
|
||||
ss.print(" resolved method %s%s%s%s of %s %s.",
|
||||
ss.print(" resolved method '%s%s",
|
||||
resolved_method->is_abstract() ? "abstract " : "",
|
||||
resolved_method->is_private() ? "private " : "",
|
||||
resolved_method->name()->as_C_string(),
|
||||
resolved_method->signature()->as_C_string(),
|
||||
resolved_method->is_private() ? "private " : "");
|
||||
resolved_method->signature()->print_as_signature_external_return_type(&ss);
|
||||
ss.print(" %s(", resolved_method->name()->as_C_string());
|
||||
resolved_method->signature()->print_as_signature_external_parameters(&ss);
|
||||
ss.print(")' of %s %s.",
|
||||
resolved_klass->external_kind(),
|
||||
resolved_klass->external_name());
|
||||
|
||||
if (selected_method.not_null() && !(resolved_method == selected_method)) {
|
||||
ss.print(" Selected method is %s%s%s.",
|
||||
ss.print(" Selected method is '%s%s",
|
||||
selected_method->is_abstract() ? "abstract " : "",
|
||||
selected_method->is_private() ? "private " : "",
|
||||
selected_method->name_and_sig_as_C_string());
|
||||
selected_method->is_private() ? "private " : "");
|
||||
selected_method->print_external_name(&ss);
|
||||
ss.print("'.");
|
||||
}
|
||||
|
||||
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
|
||||
|
|
|
@ -182,7 +182,6 @@ class LinkInfo : public StackObj {
|
|||
methodHandle current_method() const { return _current_method; }
|
||||
constantTag tag() const { return _tag; }
|
||||
bool check_access() const { return _check_access; }
|
||||
char* method_string() const;
|
||||
|
||||
void print() PRODUCT_RETURN;
|
||||
};
|
||||
|
|
|
@ -1000,14 +1000,17 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
|
|||
if ((callee->is_interface() && m_tag.is_method()) ||
|
||||
((!callee->is_interface() && m_tag.is_interface_method()))) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[400];
|
||||
jio_snprintf(buf, sizeof(buf),
|
||||
"Inconsistent constant pool data in classfile for class %s. "
|
||||
"Method %s%s at index %d is %s and should be %s",
|
||||
callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index,
|
||||
callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
|
||||
callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
stringStream ss;
|
||||
ss.print("Inconsistent constant pool data in classfile for class %s. "
|
||||
"Method '", callee->name()->as_C_string());
|
||||
signature->print_as_signature_external_return_type(&ss);
|
||||
ss.print(" %s(", name->as_C_string());
|
||||
signature->print_as_signature_external_parameters(&ss);
|
||||
ss.print(")' at index %d is %s and should be %s",
|
||||
index,
|
||||
callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
|
||||
callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
Klass* klass = this_cp->pool_holder();
|
||||
|
|
|
@ -500,11 +500,11 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
|||
if (failed_type_symbol != NULL) {
|
||||
stringStream ss;
|
||||
ss.print("loader constraint violation for class %s: when selecting "
|
||||
"overriding method %s the class loader %s of the "
|
||||
"overriding method '", klass->external_name());
|
||||
target_method()->print_external_name(&ss),
|
||||
ss.print("' the class loader %s of the "
|
||||
"selected method's type %s, and the class loader %s for its super "
|
||||
"type %s have different Class objects for the type %s used in the signature (%s; %s)",
|
||||
klass->external_name(),
|
||||
target_method()->name_and_sig_as_C_string(),
|
||||
target_klass->class_loader_data()->loader_name_and_id(),
|
||||
target_klass->external_name(),
|
||||
super_klass->class_loader_data()->loader_name_and_id(),
|
||||
|
@ -1227,15 +1227,16 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Insta
|
|||
if (failed_type_symbol != NULL) {
|
||||
stringStream ss;
|
||||
ss.print("loader constraint violation in interface itable"
|
||||
" initialization for class %s: when selecting method %s the"
|
||||
" class loader %s for super interface %s, and the class"
|
||||
" loader %s of the selected method's type, %s have"
|
||||
" initialization for class %s: when selecting method '",
|
||||
_klass->external_name());
|
||||
m->print_external_name(&ss),
|
||||
ss.print("' the class loader %s for super interface %s, and the class"
|
||||
" loader %s of the selected method's %s, %s have"
|
||||
" different Class objects for the type %s used in the signature (%s; %s)",
|
||||
_klass->external_name(),
|
||||
m->name_and_sig_as_C_string(),
|
||||
interf->class_loader_data()->loader_name_and_id(),
|
||||
interf->external_name(),
|
||||
target()->method_holder()->class_loader_data()->loader_name_and_id(),
|
||||
target()->method_holder()->external_kind(),
|
||||
target()->method_holder()->external_name(),
|
||||
failed_type_symbol->as_klass_external_name(),
|
||||
interf->class_in_module_of_loader(false, true),
|
||||
|
|
|
@ -178,6 +178,27 @@ char* Method::name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol
|
|||
return buf;
|
||||
}
|
||||
|
||||
const char* Method::external_name() const {
|
||||
return external_name(constants()->pool_holder(), name(), signature());
|
||||
}
|
||||
|
||||
void Method::print_external_name(outputStream *os) const {
|
||||
print_external_name(os, constants()->pool_holder(), name(), signature());
|
||||
}
|
||||
|
||||
const char* Method::external_name(Klass* klass, Symbol* method_name, Symbol* signature) {
|
||||
stringStream ss;
|
||||
print_external_name(&ss, klass, method_name, signature);
|
||||
return ss.as_string();
|
||||
}
|
||||
|
||||
void Method::print_external_name(outputStream *os, Klass* klass, Symbol* method_name, Symbol* signature) {
|
||||
signature->print_as_signature_external_return_type(os);
|
||||
os->print(" %s.%s(", klass->external_name(), method_name->as_C_string());
|
||||
signature->print_as_signature_external_parameters(os);
|
||||
os->print(")");
|
||||
}
|
||||
|
||||
int Method::fast_exception_handler_bci_for(const methodHandle& mh, Klass* ex_klass, int throw_bci, TRAPS) {
|
||||
// exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index)
|
||||
// access exception table
|
||||
|
|
|
@ -180,8 +180,8 @@ class Method : public Metadata {
|
|||
}
|
||||
|
||||
// Helper routine: get klass name + "." + method name + signature as
|
||||
// C string, for the purpose of providing more useful NoSuchMethodErrors
|
||||
// and fatal error handling. The string is allocated in resource
|
||||
// C string, for the purpose of providing more useful
|
||||
// fatal error handling. The string is allocated in resource
|
||||
// area if a buffer is not provided by the caller.
|
||||
char* name_and_sig_as_C_string() const;
|
||||
char* name_and_sig_as_C_string(char* buf, int size) const;
|
||||
|
@ -190,6 +190,18 @@ class Method : public Metadata {
|
|||
static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature);
|
||||
static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size);
|
||||
|
||||
// Get return type + klass name + "." + method name + ( parameters types )
|
||||
// as a C string or print it to an outputStream.
|
||||
// This is to be used to assemble strings passed to Java, so that
|
||||
// the text more resembles Java code. Used in exception messages.
|
||||
// Memory is allocated in the resource area; the caller needs
|
||||
// a ResourceMark.
|
||||
const char* external_name() const;
|
||||
void print_external_name(outputStream *os) const;
|
||||
|
||||
static const char* external_name( Klass* klass, Symbol* method_name, Symbol* signature);
|
||||
static void print_external_name(outputStream *os, Klass* klass, Symbol* method_name, Symbol* signature);
|
||||
|
||||
Bytecodes::Code java_code_at(int bci) const {
|
||||
return Bytecodes::java_code_at(this, bcp_from(bci));
|
||||
}
|
||||
|
|
|
@ -200,6 +200,66 @@ const char* Symbol::as_klass_external_name() const {
|
|||
return str;
|
||||
}
|
||||
|
||||
static void print_class(outputStream *os, char *class_str, int len) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (class_str[i] == '/') {
|
||||
os->put('.');
|
||||
} else {
|
||||
os->put(class_str[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_array(outputStream *os, char *array_str, int len) {
|
||||
int dimensions = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (array_str[i] == '[') {
|
||||
dimensions++;
|
||||
} else if (array_str[i] == 'L') {
|
||||
// Expected format: L<type name>;. Skip 'L' and ';' delimiting the type name.
|
||||
print_class(os, array_str+i+1, len-i-2);
|
||||
break;
|
||||
} else {
|
||||
os->print("%s", type2name(char2type(array_str[i])));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < dimensions; ++i) {
|
||||
os->print("[]");
|
||||
}
|
||||
}
|
||||
|
||||
void Symbol::print_as_signature_external_return_type(outputStream *os) {
|
||||
for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
|
||||
if (ss.at_return_type()) {
|
||||
if (ss.is_array()) {
|
||||
print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
|
||||
} else if (ss.is_object()) {
|
||||
// Expected format: L<type name>;. Skip 'L' and ';' delimiting the class name.
|
||||
print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
|
||||
} else {
|
||||
os->print("%s", type2name(ss.type()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Symbol::print_as_signature_external_parameters(outputStream *os) {
|
||||
bool first = true;
|
||||
for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
|
||||
if (ss.at_return_type()) break;
|
||||
if (!first) { os->print(", "); }
|
||||
if (ss.is_array()) {
|
||||
print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
|
||||
} else if (ss.is_object()) {
|
||||
// Skip 'L' and ';'.
|
||||
print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
|
||||
} else {
|
||||
os->print("%s", type2name(ss.type()));
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment refcount while checking for zero. If the Symbol's refcount becomes zero
|
||||
// a thread could be concurrently removing the Symbol. This is used during SymbolTable
|
||||
// lookup to avoid reviving a dead Symbol.
|
||||
|
|
|
@ -229,6 +229,15 @@ class Symbol : public MetaspaceObj {
|
|||
const char* as_klass_external_name() const;
|
||||
const char* as_klass_external_name(char* buf, int size) const;
|
||||
|
||||
// Treating the symbol as a signature, print the return
|
||||
// type to the outputStream. Prints external names as 'double' or
|
||||
// 'java.lang.Object[][]'.
|
||||
void print_as_signature_external_return_type(outputStream *os);
|
||||
// Treating the symbol as a signature, print the parameter types
|
||||
// seperated by ', ' to the outputStream. Prints external names as
|
||||
// 'double' or 'java.lang.Object[][]'.
|
||||
void print_as_signature_external_parameters(outputStream *os);
|
||||
|
||||
void metaspace_pointers_do(MetaspaceClosure* it);
|
||||
MetaspaceObj::Type type() const { return SymbolType; }
|
||||
|
||||
|
|
|
@ -2955,8 +2955,9 @@ static bool register_native(Klass* k, Symbol* name, Symbol* signature, address e
|
|||
if (method == NULL) {
|
||||
ResourceMark rm;
|
||||
stringStream st;
|
||||
st.print("Method %s name or signature does not match",
|
||||
Method::name_and_sig_as_C_string(k, name, signature));
|
||||
st.print("Method '");
|
||||
Method::print_external_name(&st, k, name, signature);
|
||||
st.print("' name or signature does not match");
|
||||
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
|
||||
}
|
||||
if (!method->is_native()) {
|
||||
|
@ -2965,8 +2966,9 @@ static bool register_native(Klass* k, Symbol* name, Symbol* signature, address e
|
|||
if (method == NULL) {
|
||||
ResourceMark rm;
|
||||
stringStream st;
|
||||
st.print("Method %s is not declared as native",
|
||||
Method::name_and_sig_as_C_string(k, name, signature));
|
||||
st.print("Method '");
|
||||
Method::print_external_name(&st, k, name, signature);
|
||||
st.print("' is not declared as native");
|
||||
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,8 +380,11 @@ address NativeLookup::lookup_base(const methodHandle& method, bool& in_base_libr
|
|||
if (entry != NULL) return entry;
|
||||
|
||||
// Native function not found, throw UnsatisfiedLinkError
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(),
|
||||
method->name_and_sig_as_C_string());
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
method->print_external_name(&ss);
|
||||
ss.print("'");
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -151,8 +151,8 @@ int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream,
|
|||
index == start_index && method->caller_sensitive()) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
|
||||
err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
|
||||
method->name_and_sig_as_C_string()));
|
||||
err_msg("StackWalker::getCallerClass called from @CallerSensitive '%s' method",
|
||||
method->external_name()));
|
||||
}
|
||||
// fill in StackFrameInfo and initialize MemberName
|
||||
stream.fill_frame(index, frames_array, method, CHECK_0);
|
||||
|
|
|
@ -1085,11 +1085,12 @@ static oop invoke(InstanceKlass* klass,
|
|||
if (method->is_abstract()) {
|
||||
// new default: 6531596
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
Method::print_external_name(&ss, target_klass, method->name(), method->signature());
|
||||
ss.print("'");
|
||||
Handle h_origexception = Exceptions::new_exception(THREAD,
|
||||
vmSymbols::java_lang_AbstractMethodError(),
|
||||
Method::name_and_sig_as_C_string(target_klass,
|
||||
method->name(),
|
||||
method->signature()));
|
||||
vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
|
||||
JavaCallArguments args(h_origexception);
|
||||
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
|
||||
vmSymbols::throwable_void_signature(),
|
||||
|
@ -1104,10 +1105,13 @@ static oop invoke(InstanceKlass* klass,
|
|||
// an internal vtable bug. If you ever get this please let Karen know.
|
||||
if (method.is_null()) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
|
||||
Method::name_and_sig_as_C_string(klass,
|
||||
reflected_method->name(),
|
||||
reflected_method->signature()));
|
||||
stringStream ss;
|
||||
ss.print("'");
|
||||
Method::print_external_name(&ss, klass,
|
||||
reflected_method->name(),
|
||||
reflected_method->signature());
|
||||
ss.print("'");
|
||||
THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string());
|
||||
}
|
||||
|
||||
assert(ptypes->is_objArray(), "just checking");
|
||||
|
|
|
@ -38,19 +38,19 @@ public class Test {
|
|||
// Break expected error messages into 3 parts since the loader name includes its identity
|
||||
// hash which is unique and can't be compared against.
|
||||
static String expectedErrorMessage1_part1 = "loader constraint violation in interface itable initialization for " +
|
||||
"class test.C: when selecting method test.I.m()Ltest/Foo; the class loader " +
|
||||
"class test.C: when selecting method 'test.Foo test.I.m()' the class loader " +
|
||||
"PreemptingClassLoader @";
|
||||
static String expectedErrorMessage1_part2 = " for super interface test.I, and the class loader 'app' of the " +
|
||||
"selected method's type, test.J have different Class objects for the " +
|
||||
"selected method's interface, test.J have different Class objects for the " +
|
||||
"type test.Foo used in the signature (test.I is in unnamed module of loader " +
|
||||
"PreemptingClassLoader @";
|
||||
static String expectedErrorMessage1_part3 = ", parent loader 'app'; test.J is in unnamed module of loader 'app')";
|
||||
|
||||
static String expectedErrorMessage2_part1 = "loader constraint violation in interface itable initialization for " +
|
||||
"class test.C: when selecting method test.I.m()Ltest/Foo; the class loader " +
|
||||
"class test.C: when selecting method 'test.Foo test.I.m()' the class loader " +
|
||||
"'ItableLdrCnstrnt_Test_Loader' @";
|
||||
static String expectedErrorMessage2_part2 = " for super interface test.I, and the class loader 'app' of the " +
|
||||
"selected method's type, test.J have different Class objects for the " +
|
||||
"selected method's interface, test.J have different Class objects for the " +
|
||||
"type test.Foo used in the signature (test.I is in unnamed module of loader " +
|
||||
"'ItableLdrCnstrnt_Test_Loader' @";
|
||||
static String expectedErrorMessage2_part3 = ", parent loader 'app'; test.J is in unnamed module of loader 'app')";
|
||||
|
@ -79,7 +79,9 @@ public class Test {
|
|||
if (!errorMsg.contains(expectedErrorMessage_part1) ||
|
||||
!errorMsg.contains(expectedErrorMessage_part2) ||
|
||||
!errorMsg.contains(expectedErrorMessage_part3)) {
|
||||
System.out.println("Expected: " + expectedErrorMessage_part1 + "<id>" + expectedErrorMessage_part2 + "\n" +
|
||||
System.out.println("Expected: " + expectedErrorMessage_part1 + "<id>" +
|
||||
expectedErrorMessage_part2 + "<id>" +
|
||||
expectedErrorMessage_part3 + "\n" +
|
||||
"but got: " + errorMsg);
|
||||
throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public class Test {
|
|||
// Break expected error messages into 3 parts since the loader name includes its identity
|
||||
// hash which is unique and can't be compared against.
|
||||
static String expectedErrorMessage1_part1 = "loader constraint violation for class test.Task: when " +
|
||||
"selecting overriding method test.Task.m()Ltest/Foo; the " +
|
||||
"selecting overriding method 'test.Foo test.Task.m()' the " +
|
||||
"class loader PreemptingClassLoader @";
|
||||
static String expectedErrorMessage1_part2 = " of the selected method's type test.Task, and the class " +
|
||||
"loader 'app' for its super type test.J have different Class objects " +
|
||||
|
@ -47,7 +47,7 @@ public class Test {
|
|||
static String expectedErrorMessage1_part3 = ", parent loader 'app'; test.J is in unnamed module of loader 'app')";
|
||||
|
||||
static String expectedErrorMessage2_part1 = "loader constraint violation for class test.Task: when " +
|
||||
"selecting overriding method test.Task.m()Ltest/Foo; the " +
|
||||
"selecting overriding method 'test.Foo test.Task.m()' the " +
|
||||
"class loader 'VtableLdrCnstrnt_Test_Loader' @";
|
||||
static String expectedErrorMessage2_part2 = " of the selected method's type test.Task, and the class " +
|
||||
"loader 'app' for its super type test.J have different Class objects " +
|
||||
|
|
|
@ -671,7 +671,7 @@ public class TestNestmateMembership {
|
|||
static void test_NoHostInvoke() throws Throwable {
|
||||
System.out.println("Testing for missing nest-host attribute");
|
||||
String msg = "class TestNestmateMembership$Caller tried to access " +
|
||||
"private method TestNestmateMembership$TargetNoHost.m()V";
|
||||
"private method 'void TestNestmateMembership$TargetNoHost.m()'";
|
||||
try {
|
||||
Caller.invokeTargetNoHost();
|
||||
throw new Error("Missing IllegalAccessError: " + msg);
|
||||
|
@ -698,7 +698,7 @@ public class TestNestmateMembership {
|
|||
}
|
||||
|
||||
msg = "class TestNestmateMembership$CallerNoHost tried to access " +
|
||||
"private method TestNestmateMembership$Target.m()V";
|
||||
"private method 'void TestNestmateMembership$Target.m()'";
|
||||
try {
|
||||
CallerNoHost.invokeTarget();
|
||||
throw new Error("Missing IllegalAccessError: " + msg);
|
||||
|
@ -707,7 +707,7 @@ public class TestNestmateMembership {
|
|||
check_expected(expected, msg);
|
||||
}
|
||||
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||
"method TestNestmateMembership$TargetNoHost.m()V";
|
||||
"method 'void TestNestmateMembership$TargetNoHost.m()'";
|
||||
try {
|
||||
CallerNoHost.invokeTargetNoHost();
|
||||
throw new Error("Missing IllegalAccessError: " + msg);
|
||||
|
@ -950,7 +950,7 @@ public class TestNestmateMembership {
|
|||
static void test_NoHostConstruct() throws Throwable {
|
||||
System.out.println("Testing for missing nest-host attribute");
|
||||
String msg = "class TestNestmateMembership$Caller tried to access private " +
|
||||
"method TestNestmateMembership$TargetNoHost.<init>()V";
|
||||
"method 'void TestNestmateMembership$TargetNoHost.<init>()'";
|
||||
try {
|
||||
Caller.newTargetNoHost();
|
||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||
|
@ -977,7 +977,7 @@ public class TestNestmateMembership {
|
|||
}
|
||||
|
||||
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||
"method TestNestmateMembership$Target.<init>()V";
|
||||
"method 'void TestNestmateMembership$Target.<init>()'";
|
||||
try {
|
||||
CallerNoHost.newTarget();
|
||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||
|
@ -986,7 +986,7 @@ public class TestNestmateMembership {
|
|||
check_expected(expected, msg);
|
||||
}
|
||||
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||
"method TestNestmateMembership$TargetNoHost.<init>()V";
|
||||
"method 'void TestNestmateMembership$TargetNoHost.<init>()'";
|
||||
try {
|
||||
CallerNoHost.newTargetNoHost();
|
||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||
|
|
|
@ -51,7 +51,7 @@ public class TestConstructorHierarchy {
|
|||
throw new Error("Unexpected construction of ExternalSuper");
|
||||
}
|
||||
catch (IllegalAccessError iae) {
|
||||
if (iae.getMessage().contains("class TestConstructorHierarchy tried to access private method ExternalSuper.<init>()V")) {
|
||||
if (iae.getMessage().contains("class TestConstructorHierarchy tried to access private method 'void ExternalSuper.<init>()'")) {
|
||||
System.out.println("Got expected exception constructing ExternalSuper: " + iae);
|
||||
}
|
||||
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
||||
|
@ -61,7 +61,7 @@ public class TestConstructorHierarchy {
|
|||
throw new Error("Unexpected construction of NestedA and supers");
|
||||
}
|
||||
catch (IllegalAccessError iae) {
|
||||
if (iae.getMessage().contains("class TestConstructorHierarchy$NestedA tried to access private method ExternalSuper.<init>()V")) {
|
||||
if (iae.getMessage().contains("class TestConstructorHierarchy$NestedA tried to access private method 'void ExternalSuper.<init>()'")) {
|
||||
System.out.println("Got expected exception constructing NestedA: " + iae);
|
||||
}
|
||||
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
||||
|
@ -71,7 +71,7 @@ public class TestConstructorHierarchy {
|
|||
throw new Error("Unexpected construction of ExternalSub");
|
||||
}
|
||||
catch (IllegalAccessError iae) {
|
||||
if (iae.getMessage().contains("class ExternalSub tried to access private method TestConstructorHierarchy$NestedA.<init>()V")) {
|
||||
if (iae.getMessage().contains("class ExternalSub tried to access private method 'void TestConstructorHierarchy$NestedA.<init>()'")) {
|
||||
System.out.println("Got expected exception constructing ExternalSub: " + iae);
|
||||
}
|
||||
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
||||
|
|
|
@ -99,11 +99,11 @@ public class AbstractMethodErrorTest {
|
|||
}
|
||||
|
||||
private static String expectedErrorMessageAME1_1 =
|
||||
"Missing implementation of resolved method abstract " +
|
||||
"anAbstractMethod()Ljava/lang/String; of abstract class AME1_B.";
|
||||
"Missing implementation of resolved method 'abstract " +
|
||||
"java.lang.String anAbstractMethod()' of abstract class AME1_B.";
|
||||
private static String expectedErrorMessageAME1_2 =
|
||||
"Receiver class AME1_E does not define or inherit an implementation of the " +
|
||||
"resolved method abstract aFunctionOfMyInterface()Ljava/lang/String; of " +
|
||||
"resolved method 'abstract java.lang.String aFunctionOfMyInterface()' of " +
|
||||
"interface AME1_C.";
|
||||
|
||||
public static void test_ame1() {
|
||||
|
@ -158,11 +158,11 @@ public class AbstractMethodErrorTest {
|
|||
}
|
||||
|
||||
private static String expectedErrorMessageAME2_Interpreted =
|
||||
"Missing implementation of resolved method abstract " +
|
||||
"aFunctionOfMyInterface()V of interface AME2_A.";
|
||||
"Missing implementation of resolved method 'abstract " +
|
||||
"void aFunctionOfMyInterface()' of interface AME2_A.";
|
||||
private static String expectedErrorMessageAME2_Compiled =
|
||||
"Receiver class AME2_C does not define or inherit an implementation of the resolved method " +
|
||||
"abstract aFunctionOfMyInterface()V of interface AME2_A.";
|
||||
"'abstract void aFunctionOfMyInterface()' of interface AME2_A.";
|
||||
|
||||
public AbstractMethodErrorTest() throws InstantiationException, IllegalAccessException {
|
||||
try {
|
||||
|
@ -228,7 +228,7 @@ public class AbstractMethodErrorTest {
|
|||
|
||||
private static String expectedErrorMessageAME3_1 =
|
||||
"Receiver class AME3_C does not define or inherit an implementation of the resolved method " +
|
||||
"ma()V of class AME3_A. Selected method is abstract AME3_B.ma()V.";
|
||||
"'void ma()' of class AME3_A. Selected method is 'abstract void AME3_B.ma()'.";
|
||||
|
||||
// Testing abstract class that extends a class that has an implementation.
|
||||
// Loop so that method gets eventually compiled/osred.
|
||||
|
@ -259,7 +259,7 @@ public class AbstractMethodErrorTest {
|
|||
|
||||
private static String expectedErrorMessageAME3_2 =
|
||||
"Receiver class AME3_C does not define or inherit an implementation of " +
|
||||
"the resolved method abstract ma()V of abstract class AME3_B.";
|
||||
"the resolved method 'abstract void ma()' of abstract class AME3_B.";
|
||||
|
||||
// Testing abstract class that extends a class that has an implementation.
|
||||
// Loop so that method gets eventually compiled/osred.
|
||||
|
@ -289,7 +289,7 @@ public class AbstractMethodErrorTest {
|
|||
}
|
||||
|
||||
private static String expectedErrorMessageAME4 =
|
||||
"Missing implementation of resolved method abstract ma()V of " +
|
||||
"Missing implementation of resolved method 'abstract void ma()' of " +
|
||||
"abstract class AME4_B.";
|
||||
|
||||
// Testing abstract class that extends a class that has an implementation.
|
||||
|
@ -336,7 +336,7 @@ public class AbstractMethodErrorTest {
|
|||
}
|
||||
|
||||
private static String expectedErrorMessageAME5_VtableStub =
|
||||
"Receiver class AME5_B does not define or inherit an implementation of the resolved method abstract mc()V " +
|
||||
"Receiver class AME5_B does not define or inherit an implementation of the resolved method 'abstract void mc()' " +
|
||||
"of abstract class AME5_A.";
|
||||
|
||||
// AbstractMethodErrors detected in vtable stubs.
|
||||
|
@ -409,7 +409,7 @@ public class AbstractMethodErrorTest {
|
|||
|
||||
private static String expectedErrorMessageAME6_ItableStub =
|
||||
"Receiver class AME6_B does not define or inherit an implementation of the resolved" +
|
||||
" method abstract mc()V of interface AME6_A.";
|
||||
" method 'abstract void mc()' of interface AME6_A.";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// AbstractMethodErrors detected in itable stubs.
|
||||
|
|
|
@ -141,7 +141,7 @@ abstract public class IllegalAccessErrorTest {
|
|||
private static void iae4_m() { }
|
||||
|
||||
private static String expectedErrorMessage4 =
|
||||
"class test.Runner4 tried to access private method test.IllegalAccessErrorTest.iae4_m()V " +
|
||||
"class test.Runner4 tried to access private method 'void test.IllegalAccessErrorTest.iae4_m()' " +
|
||||
"(test.Runner4 and test.IllegalAccessErrorTest are in unnamed module of loader 'app')";
|
||||
|
||||
// Test according to java/lang/invoke/DefineClassTest.java
|
||||
|
@ -264,7 +264,7 @@ abstract public class IllegalAccessErrorTest {
|
|||
}
|
||||
|
||||
private static String expectedErrorMessage7_1 =
|
||||
"class test.IAE78_B tried to access method test.IAE78_A.<init>()V " +
|
||||
"class test.IAE78_B tried to access method 'void test.IAE78_A.<init>()' " +
|
||||
"(test.IAE78_B is in unnamed module of loader 'test7_method_CL' @";
|
||||
private static String expectedErrorMessage7_2 =
|
||||
"; test.IAE78_A is in unnamed module of loader 'app')";
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package test;
|
||||
|
||||
/* Method ma() is missing in this implementation to cause error. */
|
||||
|
||||
class TeMe3_C extends TeMe3_B {
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method TeMe3_B."<init>":()V;
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Check that methods are printed properly.
|
||||
* @compile -encoding UTF-8 TestPrintingMethods.java
|
||||
* @compile TeMe3_C.jasm
|
||||
* @run main/othervm -Xbootclasspath/a:. test.TestPrintingMethods
|
||||
*/
|
||||
|
||||
package test;
|
||||
|
||||
public class TestPrintingMethods {
|
||||
|
||||
private static String expectedErrorMessage_VV = "void test.TeMe3_B.ma()";
|
||||
private static String expectedErrorMessage_integral = "double[][] test.TeMe3_B.ma(int, boolean, byte[][], float)";
|
||||
private static String expectedErrorMessage_classes = "test.TeMe3_B[][] test.TeMe3_B.ma(java.lang.Object[][][])";
|
||||
private static String expectedErrorMessage_unicode = "java.lang.Object test.TeMe3_B.m\u20ac\u00a3a(java.lang.Object)";
|
||||
|
||||
static void checkMsg(Error e, String expected) throws Exception {
|
||||
String errorMsg = e.getMessage();
|
||||
if (errorMsg == null) {
|
||||
throw new RuntimeException("Caught AbstractMethodError with empty message.");
|
||||
} else if (errorMsg.contains(expected)) {
|
||||
System.out.println("Passed with message: " + errorMsg);
|
||||
} else {
|
||||
System.out.println("Expected method to be printed as \"" + expected + "\"\n" +
|
||||
"in exception message: " + errorMsg);
|
||||
throw new RuntimeException("Method not printed as expected.");
|
||||
}
|
||||
}
|
||||
|
||||
// Call various missing methods to check that the exception
|
||||
// message contains the proper string for the method name and
|
||||
// signature. We expect Java-like printing of parameters etc.
|
||||
static void test() throws Exception {
|
||||
TeMe3_A c = new TeMe3_C();
|
||||
|
||||
try {
|
||||
c.ma();
|
||||
throw new RuntimeException("Expected AbstractMethodError was not thrown.");
|
||||
} catch (AbstractMethodError e) {
|
||||
checkMsg(e, expectedErrorMessage_VV);
|
||||
}
|
||||
|
||||
try {
|
||||
c.ma(2, true, new byte[2][3], 23.4f);
|
||||
throw new RuntimeException("Expected AbstractMethodError was not thrown.");
|
||||
} catch (AbstractMethodError e) {
|
||||
checkMsg(e, expectedErrorMessage_integral);
|
||||
}
|
||||
|
||||
try {
|
||||
c.ma(new java.lang.Object[1][2][3]);
|
||||
throw new RuntimeException("Expected AbstractMethodError was not thrown.");
|
||||
} catch (AbstractMethodError e) {
|
||||
checkMsg(e, expectedErrorMessage_classes);
|
||||
}
|
||||
|
||||
try {
|
||||
c.m\u20ac\u00a3a(new java.lang.Object());
|
||||
throw new RuntimeException("Expected AbstractMethodError was not thrown.");
|
||||
} catch (AbstractMethodError e) {
|
||||
checkMsg(e, expectedErrorMessage_unicode);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper classes to test abstract method error.
|
||||
//
|
||||
// Errorneous versions of these classes are implemented in java
|
||||
// assembler.
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test AbstractMethod error shadowing existing implementation.
|
||||
//
|
||||
// Class hierachy:
|
||||
//
|
||||
// A // A class implementing m() and similar.
|
||||
// |
|
||||
// B // An abstract class defining m() abstract.
|
||||
// |
|
||||
// C // An errorneous class lacking an implementation of m().
|
||||
//
|
||||
class TeMe3_A {
|
||||
public void ma() {
|
||||
System.out.print("A.ma()");
|
||||
}
|
||||
public double[][] ma(int i, boolean z, byte[][] b, float f) {
|
||||
return null;
|
||||
}
|
||||
public TeMe3_B[][] ma(java.lang.Object[][][] o) {
|
||||
return null;
|
||||
}
|
||||
public java.lang.Object m\u20ac\u00a3a(java.lang.Object s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TeMe3_B extends TeMe3_A {
|
||||
public abstract void ma();
|
||||
public abstract double[][] ma(int i, boolean z, byte[][] b, float f);
|
||||
public abstract TeMe3_B[][] ma(java.lang.Object[][][] o);
|
||||
public abstract java.lang.Object m\u20ac\u00a3a(java.lang.Object s);
|
||||
}
|
||||
|
||||
// An errorneous version of this class is implemented in java
|
||||
// assembler.
|
||||
class TeMe3_C extends TeMe3_B {
|
||||
// These methods are missing in the .jasm implementation.
|
||||
public void ma() {
|
||||
System.out.print("C.ma()");
|
||||
}
|
||||
public double[][] ma(int i, boolean z, byte[][] b, float f) {
|
||||
return new double[2][2];
|
||||
}
|
||||
public TeMe3_B[][] ma(java.lang.Object[][][] o) {
|
||||
return new TeMe3_C[3][3];
|
||||
}
|
||||
public java.lang.Object m\u20ac\u00a3a(java.lang.Object s) {
|
||||
return new java.lang.Object();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -103,7 +103,7 @@ public class ExpQualToM1PrivateMethodIAE {
|
|||
// java.lang.IllegalAccessError:
|
||||
// tried to access private method p2.c2.method2()V from class p1.c1 (p2.c2 is in module m2x of loader
|
||||
// myloaders.MySameClassLoader @<id>; p1.c1 is in module m1x of loader myloaders.MySameClassLoader @<id>)
|
||||
if (!message.contains("class p1.c1 tried to access private method p2.c2.method2()V " +
|
||||
if (!message.contains("class p1.c1 tried to access private method 'void p2.c2.method2()' " +
|
||||
"(p1.c1 is in module m1x of loader myloaders.MySameClassLoader @") ||
|
||||
!message.contains("; p2.c2 is in module m2x of loader myloaders.MySameClassLoader @")) {
|
||||
throw new RuntimeException("Test Failed, an IAE was thrown with the wrong message: " + e.toString());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue