--- old/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java 2018-05-04 00:47:16.716791061 -0400 +++ new/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java 2018-05-04 00:47:14.896685501 -0400 @@ -84,7 +84,9 @@ switch (refKind) { case REF_invokeSpecial: { member = member.asSpecial(); - LambdaForm lform = preparedLambdaForm(member, callerClass); + // if caller is an interface we need to adapt to get the + // receiver check inserted + LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface()); Class checkClass = refc; // Class to use for receiver type check if (callerClass != null) { checkClass = callerClass; // potentially strengthen to caller class @@ -92,11 +94,12 @@ return new Special(mtype, lform, member, checkClass); } case REF_invokeInterface: { - LambdaForm lform = preparedLambdaForm(member, callerClass); + // we always adapt 'special' when dealing with interfaces + LambdaForm lform = preparedLambdaForm(member, true); return new Interface(mtype, lform, member, refc); } default: { - LambdaForm lform = preparedLambdaForm(member, callerClass); + LambdaForm lform = preparedLambdaForm(member); return new DirectMethodHandle(mtype, lform, member); } } @@ -166,11 +169,15 @@ * Cache and share this structure among all methods with * the same basicType and refKind. */ - private static LambdaForm preparedLambdaForm(MemberName m, Class callerClass) { + private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) { assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead MethodType mtype = m.getInvocationType().basicType(); assert(!m.isMethodHandleInvoke()) : m; int which; + // MemberName.getReferenceKind may be different from 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; @@ -184,7 +191,7 @@ preparedLambdaForm(mtype, which); which = LF_INVSTATIC_INIT; } - if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) { + if (which == LF_INVSPECIAL && adaptToSpecialIfc) { which = LF_INVSPECIAL_IFC; } LambdaForm lform = preparedLambdaForm(mtype, which); @@ -196,7 +203,7 @@ } private static LambdaForm preparedLambdaForm(MemberName m) { - return preparedLambdaForm(m, null); + return preparedLambdaForm(m, false); } private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {