< prev index next >

src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java

Print this page

        

@@ -169,10 +169,14 @@
     private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) {
         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
         MethodType mtype = m.getInvocationType().basicType();
         assert(!m.isMethodHandleInvoke()) : m;
         int which;
+        // MemberName.getReferenceKind may be different to the 'kind' passed to
+        // DMH.make. Specifically private/final methods that use a direct call
+        // have been adapted to REF_invokeSpecial, even though the actual
+        // invocation mode may be invokevirtual or invokeinterface.
         switch (m.getReferenceKind()) {
         case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
         case REF_invokeStatic:     which = LF_INVSTATIC;     break;
         case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
         case REF_invokeInterface:  which = LF_INVINTERFACE;  break;

@@ -182,11 +186,17 @@
         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
             // precompute the barrier-free version:
             preparedLambdaForm(mtype, which);
             which = LF_INVSTATIC_INIT;
         }
-        if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) {
+        // Direct calls involving interfaces require additional specialization to add
+        // in a receiver typecheck. For true invokespecial we need to inspect the callerClass
+        // for being an interface (which implies REFC is also an interface). For invokeinterface
+        // we always need the check. If the declaring class is an interface, and the method is not
+        // static, then this must be an invokeinterface.
+        if (which == LF_INVSPECIAL && ((callerClass != null && callerClass.isInterface()) ||
+                                       (!m.isStatic() && m.getDeclaringClass().isInterface()))) {
             which = LF_INVSPECIAL_IFC;
         }
         LambdaForm lform = preparedLambdaForm(mtype, which);
         maybeCompile(lform, m);
         assert(lform.methodType().dropParameterTypes(0, 1)
< prev index next >