src/share/vm/interpreter/linkResolver.cpp

Print this page

        

@@ -240,20 +240,20 @@
 //
 // According to JVM spec. $5.4.3c & $5.4.3d
 
 // 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();
     if (default_methods != NULL) {
       result_oop = InstanceKlass::find_method(default_methods, name, signature);
     }
   }
 
-  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.
       return;
     }

@@ -265,12 +265,12 @@
 // Looks up method in classes, then looks up local default methods
 void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
   Method* result_oop = klass->uncached_lookup_method(name, signature);
   result = methodHandle(THREAD, result_oop);
   while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) {
-    klass = KlassHandle(THREAD, result->method_holder()->super());
-    result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
+    KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super());
+    result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature));
   }
 
   if (result.is_null()) {
     Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
     if (default_methods != NULL) {

@@ -501,15 +501,18 @@
       return;
     }
   }
 
   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 {
+  } else if (!resolved_klass->is_interface()) {
     resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
+  } else {
+    bool nostatics = (code == Bytecodes::_invokestatic) ? false : true;
+    resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK);
   }
 }
 
 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
                                   Symbol* method_name, Symbol* method_signature,

@@ -526,11 +529,11 @@
         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);
+  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
     lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
 

@@ -610,22 +613,24 @@
 void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
                                             KlassHandle resolved_klass,
                                             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()) {
     ResourceMark rm(THREAD);
     char buf[200];
     jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name());
     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   // 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
     lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
     if (resolved_method.is_null()) {

@@ -636,10 +641,20 @@
                                                         method_name,
                                                         method_signature));
     }
   }
 
+  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");
 
     // check if method can be accessed by the referring class

@@ -862,11 +877,15 @@
 // throws linktime exceptions
 void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass,
                                                   Symbol* method_name, Symbol* method_signature,
                                                   KlassHandle current_klass, bool check_access, TRAPS) {
 
+  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
   if (!resolved_method->is_static()) {
     ResourceMark rm(THREAD);

@@ -896,11 +915,15 @@
   // local private method invocation, for classes and interfaces
   // superclass.method, which can also resolve to a default method
   // and the selected method is recalculated relative to the direct superclass
   // superinterface.method, which explicitly does not check shadowing
 
+  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() &&
       resolved_method->method_holder() != resolved_klass()) {
     ResourceMark rm(THREAD);

@@ -1217,11 +1240,11 @@
 
 // throws linktime exceptions
 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");
 }