8268192: LambdaMetafactory with invokespecial causes VerificationError

Reviewed-by: psandoz, mchung
This commit is contained in:
Dan Smith 2021-06-09 23:57:41 +00:00
parent b41f3f8ed5
commit 58ba48b7b8
3 changed files with 15 additions and 20 deletions

View file

@ -180,8 +180,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
implMethodDesc = implInfo.getMethodType().toMethodDescriptorString();
constructorType = factoryType.changeReturnType(Void.TYPE);
lambdaClassName = lambdaClassName(targetClass);
useImplMethodHandle = !Modifier.isPublic(implInfo.getModifiers()) &&
!VerifyAccess.isSamePackage(implClass, implInfo.getDeclaringClass());
// If the target class invokes a protected method inherited from a
// superclass in a different package, or does 'invokespecial', the
// lambda class has no access to the resolved method. Instead, we need
// to pass the live implementation method handle to the proxy class
// to invoke directly. (javac prefers to avoid this situation by
// generating bridges in the target class)
useImplMethodHandle = (Modifier.isProtected(implInfo.getModifiers()) &&
!VerifyAccess.isSamePackage(implClass, implInfo.getDeclaringClass())) ||
implKind == H_INVOKESPECIAL;
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
int parameterCount = factoryType.parameterCount();
if (parameterCount > 0) {
@ -394,13 +401,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
// this class is linked at the indy callsite; so define a hidden nestmate
Lookup lookup;
if (useImplMethodHandle) {
// If the target class invokes a method reference this::m which is
// resolved to a protected method inherited from a superclass in a different
// package, the target class does not have a bridge and this method reference
// has been changed from public to protected after the target class was compiled.
// This lambda proxy class has no access to the resolved method.
// So this workaround by passing the live implementation method handle
// to the proxy class to invoke directly.
lookup = caller.defineHiddenClassWithClassData(classBytes, implementation, !disableEagerInitialization,
NESTMATE, STRONG);
} else {