--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Mon Dec 02 11:42:10 2013 +0100
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Tue Dec 03 08:36:15 2013 -0800
@@ -242,7 +242,7 @@
// Look up method in klasses, including static methods
// Then look up local default methods
-void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
+void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, TRAPS) {
Method* result_oop = klass->uncached_lookup_method(name, signature);
if (result_oop == NULL) {
Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
@@ -251,7 +251,7 @@
}
}
- if (EnableInvokeDynamic && result_oop != NULL) {
+ if (checkpolymorphism && EnableInvokeDynamic && result_oop != NULL) {
vmIntrinsics::ID iid = result_oop->intrinsic_id();
if (MethodHandles::is_signature_polymorphic(iid)) {
// Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method.
@@ -503,11 +503,14 @@
}
if (code == Bytecodes::_invokeinterface) {
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
+ resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
} else if (code == Bytecodes::_invokevirtual) {
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+ } else if (!resolved_klass->is_interface()) {
+ resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
} else {
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
+ bool nostatics = (code == Bytecodes::_invokestatic) ? false : true;
+ resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK);
}
}
@@ -528,7 +531,7 @@
}
// 2. lookup method in resolved klass and its super klasses
- lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
+ lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, CHECK);
if (resolved_method.is_null()) { // not found in the class hierarchy
// 3. lookup method in all the interfaces implemented by the resolved klass
@@ -612,7 +615,8 @@
Symbol* method_name,
Symbol* method_signature,
KlassHandle current_klass,
- bool check_access, TRAPS) {
+ bool check_access,
+ bool nostatics, TRAPS) {
// check if klass is interface
if (!resolved_klass->is_interface()) {
@@ -623,7 +627,8 @@
}
// lookup method in this interface or its super, java.lang.Object
- lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
+ // JDK8: also look for static methods
+ lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, CHECK);
if (resolved_method.is_null()) {
// lookup method in all the super-interfaces
@@ -638,6 +643,16 @@
}
}
+ if (nostatics && 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(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ }
+
+
if (check_access) {
// JDK8 adds non-public interface methods, and accessability check requirement
assert(current_klass.not_null() , "current_klass should not be null");
@@ -864,7 +879,11 @@
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, false, CHECK);
+ if (!resolved_klass->is_interface()) {
+ resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+ } else {
+ resolve_interface_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
@@ -898,7 +917,11 @@
// 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, false, CHECK);
+ if (!resolved_klass->is_interface()) {
+ resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+ } else {
+ resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
+ }
// check if method name is <init>, that it is found in same klass as static type
if (resolved_method->name() == vmSymbols::object_initializer_name() &&
@@ -1219,7 +1242,7 @@
void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name,
Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
// normal interface method resolution
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
+ resolve_interface_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");
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Mon Dec 02 11:42:10 2013 +0100
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Tue Dec 03 08:36:15 2013 -0800
@@ -124,7 +124,7 @@
friend class klassItable;
private:
- static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+ static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, TRAPS);
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
@@ -134,7 +134,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_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool nostatics, 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);