8221470: Print methods in exception messages in java-like Syntax.
Reviewed-by: dholmes, mdoerr, coleenp
--- a/src/hotspot/share/classfile/verifier.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/classfile/verifier.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -2060,7 +2060,9 @@
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();
}
--- a/src/hotspot/share/interpreter/linkResolver.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/interpreter/linkResolver.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -264,10 +264,6 @@
_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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
}
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());
--- a/src/hotspot/share/interpreter/linkResolver.hpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/interpreter/linkResolver.hpp Thu Apr 04 09:39:44 2019 +0200
@@ -182,7 +182,6 @@
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;
};
--- a/src/hotspot/share/oops/constantPool.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/oops/constantPool.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -1000,14 +1000,17 @@
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();
--- a/src/hotspot/share/oops/klassVtable.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/oops/klassVtable.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -500,11 +500,11 @@
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 @@
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),
--- a/src/hotspot/share/oops/method.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/oops/method.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -178,6 +178,27 @@
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
--- a/src/hotspot/share/oops/method.hpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/oops/method.hpp Thu Apr 04 09:39:44 2019 +0200
@@ -180,8 +180,8 @@
}
// 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 @@
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));
}
--- a/src/hotspot/share/oops/symbol.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/oops/symbol.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -200,6 +200,66 @@
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.
--- a/src/hotspot/share/oops/symbol.hpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/oops/symbol.hpp Thu Apr 04 09:39:44 2019 +0200
@@ -229,6 +229,15 @@
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; }
--- a/src/hotspot/share/prims/jni.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/prims/jni.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -2955,8 +2955,9 @@
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 @@
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);
}
}
--- a/src/hotspot/share/prims/nativeLookup.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/prims/nativeLookup.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -380,8 +380,11 @@
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());
}
--- a/src/hotspot/share/prims/stackwalk.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/prims/stackwalk.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -151,8 +151,8 @@
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);
--- a/src/hotspot/share/runtime/reflection.cpp Thu Apr 04 17:23:05 2019 -0400
+++ b/src/hotspot/share/runtime/reflection.cpp Thu Apr 04 09:39:44 2019 +0200
@@ -1085,11 +1085,12 @@
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 @@
// 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");
--- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java Thu Apr 04 09:39:44 2019 +0200
@@ -38,19 +38,19 @@
// 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 @@
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);
}
--- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java Thu Apr 04 09:39:44 2019 +0200
@@ -38,7 +38,7 @@
// 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 @@
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 " +
--- a/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestmateMembership.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestmateMembership.java Thu Apr 04 09:39:44 2019 +0200
@@ -671,7 +671,7 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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);
--- a/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestConstructorHierarchy.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestConstructorHierarchy.java Thu Apr 04 09:39:44 2019 +0200
@@ -51,7 +51,7 @@
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 @@
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 @@
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);
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java Thu Apr 04 09:39:44 2019 +0200
@@ -99,11 +99,11 @@
}
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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.
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IllegalAccessErrorTest.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IllegalAccessErrorTest.java Thu Apr 04 09:39:44 2019 +0200
@@ -141,7 +141,7 @@
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 @@
}
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')";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TeMe3_C.jasm Thu Apr 04 09:39:44 2019 +0200
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TestPrintingMethods.java Thu Apr 04 09:39:44 2019 +0200
@@ -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();
+ }
+}
+
--- a/test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java Thu Apr 04 17:23:05 2019 -0400
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java Thu Apr 04 09:39:44 2019 +0200
@@ -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 @@
// 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());