# HG changeset patch # User acorn # Date 1381801962 14400 # Node ID 2feadfa49bb71ce79becd9a84d22cb423724107a # Parent 057f5443edabdce9aac6193abcbff2524bf7ce50 8026299: invokespecial gets ICCE when it should get AME. Reviewed-by: ccheung, coleenp diff -r 057f5443edab -r 2feadfa49bb7 hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Sat Oct 12 15:39:16 2013 -0400 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Mon Oct 14 21:52:42 2013 -0400 @@ -454,7 +454,7 @@ Symbol* method_name = vmSymbols::invoke_name(); Symbol* method_signature = pool->signature_ref_at(index); KlassHandle current_klass(THREAD, pool->pool_holder()); - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); return; } @@ -476,22 +476,34 @@ if (code == Bytecodes::_invokeinterface) { resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); + } else if (code == Bytecodes::_invokevirtual) { + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); } else { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); } } void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, bool check_access, TRAPS) { + KlassHandle current_klass, bool check_access, + bool require_methodref, TRAPS) { Handle nested_exception; - // 1. lookup method in resolved klass and its super klasses + // 1. check if methodref required, that resolved_klass is not interfacemethodref + if (require_methodref && resolved_klass->is_interface()) { + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", + resolved_klass()->external_name()); + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + } + + // 2. lookup method in resolved klass and its super klasses lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); if (resolved_method.is_null()) { // not found in the class hierarchy - // 2. lookup method in all the interfaces implemented by the resolved klass + // 3. lookup method in all the interfaces implemented by the resolved klass lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); if (resolved_method.is_null()) { @@ -505,7 +517,7 @@ } if (resolved_method.is_null()) { - // 3. method lookup failed + // 4. method lookup failed ResourceMark rm(THREAD); THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), Method::name_and_sig_as_C_string(resolved_klass(), @@ -515,15 +527,6 @@ } } - // 4. check if klass is not interface - if (resolved_klass->is_interface() && resolved_method->is_abstract()) { - ResourceMark rm(THREAD); - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", - resolved_klass()->external_name()); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); - } - // 5. check if method is concrete if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { ResourceMark rm(THREAD); @@ -833,7 +836,7 @@ Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); // check if static @@ -867,7 +870,7 @@ // and the selected method is recalculated relative to the direct superclass // superinterface.method, which explicitly does not check shadowing - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); // check if method name is , that it is found in same klass as static type if (resolved_method->name() == vmSymbols::object_initializer_name() && @@ -1013,7 +1016,7 @@ Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { // normal method resolution - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); diff -r 057f5443edab -r 2feadfa49bb7 hotspot/src/share/vm/interpreter/linkResolver.hpp --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Sat Oct 12 15:39:16 2013 -0400 +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Mon Oct 14 21:52:42 2013 -0400 @@ -136,7 +136,7 @@ static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS); static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); - static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); + static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool require_methodref, TRAPS); static void linktime_resolve_static_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); static void linktime_resolve_special_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);