Skip to content

Commit 235525e

Browse files
committed
Match RI behaviour for unrelfect with OpenJDK MHs in JDK8
This patch addresses #14985. For MethodHandles to private interface methods, the RI erroneously initializes the MethodHandle to have an InvokeInterface reference kind, leading to an invoke-time AbstractMethodError throw. As per the spec, OpenJ9 initializes MethodHandles to private interface methods to have an InvokeSpecial reference kind which does not throw the error. This distinction causes a test failure for a test reported in #14985. Though not-spec compliant, the test expects an AbstractMethodError to be thrown to conform to the RI behaviour in JDK8. For OpenJ9 MHs, MethodHandles.unreflect identifies private interface methods and installs an AbstractMethodError-thrower MH. This patch sets up a MethodHandleResolver method that installs the AbstractMethodError-thrower MH when called from OpenJDK MH unreflect implementation. Issues: #14985 Signed-off-by: Nathan Henderson <[email protected]>
1 parent e89fd87 commit 235525e

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

jcl/src/java.base/share/classes/java/lang/invoke/MethodHandleResolver.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
import java.lang.invoke.MethodHandleInfo;
4747
/*[ENDIF] JAVA_SPEC_VERSION >= 16 */
4848

49+
/*[IF OPENJDK_METHODHANDLES & (JAVA_SPEC_VERSION < 9)]*/
50+
import java.lang.reflect.Modifier;
51+
import java.lang.reflect.Method;
52+
/*[ENDIF] OPENJDK_METHODHANDLES & (JAVA_SPEC_VERSION < 9) */
53+
4954
/**
5055
* Static methods for the MethodHandle class.
5156
*/
@@ -62,6 +67,10 @@ final class MethodHandleResolver {
6267
private static final int BSM_TYPE_ARGUMENT_INDEX = 2;
6368
private static final int BSM_OPTIONAL_ARGUMENTS_START_INDEX = 3;
6469

70+
/*[IF OPENJDK_METHODHANDLES & (JAVA_SPEC_VERSION < 9)]*/
71+
private static final int VARARGS = 0x80;
72+
/*[ENDIF] OPENJDK_METHODHANDLES & (JAVA_SPEC_VERSION < 9) */
73+
6574
/*
6675
* Return the result of J9_CP_TYPE(J9Class->romClass->cpShapeDescription, index)
6776
*/
@@ -785,4 +794,51 @@ private static final Object upcallLinkCallerMethod(Class<?> callerClass, MethodT
785794
/*[ENDIF] OPENJDK_METHODHANDLES*/
786795
}
787796
/*[ENDIF] JAVA_SPEC_VERSION >= 16 */
797+
798+
/*[IF OPENJDK_METHODHANDLES & (JAVA_SPEC_VERSION < 9)]*/
799+
/**
800+
* Create a MethodHandle to throw an AbstractMethodError if the error conditions
801+
* are met. Used in MethodHandles.unreflect for OpenJDK MethodHandles to match
802+
* the RI behaviour for JDK8 for private interface methods.
803+
*
804+
* @param m the Method whose modifiers determine if an AbstractMethodError
805+
* thrower should be installed
806+
*
807+
* @return an AbstractMethodError-thrower MethodHandle or null
808+
*
809+
* @throws InternalError if the AbstractMethodError constructor cannot be found
810+
*/
811+
@SuppressWarnings("unused")
812+
public static final MethodHandle maybeCreateAbstractMethodErrorThrower(Method m) {
813+
MethodHandle result = null;
814+
Class<?> declaringClass = m.getDeclaringClass();
815+
int methodModifiers = m.getModifiers();
816+
817+
if (declaringClass.isInterface()
818+
&& !Modifier.isStatic(methodModifiers)
819+
&& Modifier.isPrivate(methodModifiers)
820+
) {
821+
MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
822+
type = type.insertParameterTypes(0, declaringClass);
823+
824+
MethodHandle thrower = MethodHandles.throwException(type.returnType(), AbstractMethodError.class);
825+
MethodHandle constructor;
826+
try {
827+
constructor = IMPL_LOOKUP.findConstructor(
828+
AbstractMethodError.class,
829+
MethodType.methodType(void.class));
830+
} catch (IllegalAccessException | NoSuchMethodException e) {
831+
throw new InternalError("Unable to find AbstractMethodError.<init>()"); //$NON-NLS-1$
832+
}
833+
result = MethodHandles.foldArguments(thrower, constructor);
834+
result = MethodHandles.dropArguments(result, 0, type.parameterList());
835+
836+
if ((methodModifiers & VARARGS) != 0) {
837+
Class<?> lastClass = result.type().lastParameterType();
838+
result = result.asVarargsCollector(lastClass);
839+
}
840+
}
841+
return result;
842+
}
843+
/*[ENDIF] OPENJDK_METHODHANDLES & (JAVA_SPEC_VERSION < 9) */
788844
}

0 commit comments

Comments
 (0)