8268192: LambdaMetafactory with invokespecial causes VerificationError
Reviewed-by: psandoz, mchung
This commit is contained in:
parent
b41f3f8ed5
commit
58ba48b7b8
@ -154,14 +154,10 @@ import static sun.invoke.util.Wrapper.isWrapperType;
|
||||
this.implClass = implInfo.getDeclaringClass();
|
||||
this.implIsInstanceMethod = true;
|
||||
|
||||
// Classes compiled prior to dynamic nestmate support invokes a private instance
|
||||
// method with REF_invokeSpecial.
|
||||
//
|
||||
// invokespecial should only be used to invoke private nestmate constructors.
|
||||
// The lambda proxy class will be defined as a nestmate of targetClass.
|
||||
// If the method to be invoked is an instance method of targetClass, then
|
||||
// convert to use invokevirtual or invokeinterface.
|
||||
if (targetClass == implClass && !implInfo.getName().equals("<init>")) {
|
||||
// Classes compiled prior to dynamic nestmate support invoke a private instance
|
||||
// method with REF_invokeSpecial. Newer classes use REF_invokeVirtual or
|
||||
// REF_invokeInterface, and we can use that instruction in the lambda class.
|
||||
if (targetClass == implClass) {
|
||||
this.implKind = implClass.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
|
||||
} else {
|
||||
this.implKind = REF_invokeSpecial;
|
||||
|
@ -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 {
|
||||
|
@ -153,9 +153,8 @@ public class MetafactoryArgValidationTest {
|
||||
amfSucceed(C.lookup, "m", toI, arr(cToVoid, C.invokeVirtualMH(), cToVoid, flagSer));
|
||||
mfSucceed(C.lookup, "m", toI, toVoid, C.invokeStaticMH(), toVoid);
|
||||
amfSucceed(C.lookup, "m", toI, arr(toVoid, C.invokeStaticMH(), toVoid, flagSer));
|
||||
// 8268192: these fail with a VerifyError, need to fix
|
||||
//mfSucceed(C.lookup, "m", toI, cToString, C.invokeSpecialMH(), cToString);
|
||||
//amfSucceed(C.lookup, "m", toI, arr(cToString, C.invokeSpecialMH(), cToString, flagSer));
|
||||
mfSucceed(C.lookup, "m", toI, cToString, C.invokeSpecialMH(), cToString);
|
||||
amfSucceed(C.lookup, "m", toI, arr(cToString, C.invokeSpecialMH(), cToString, flagSer));
|
||||
mfSucceed(C.lookup, "m", toI, toC, C.newInvokeSpecialMH(), toC);
|
||||
amfSucceed(C.lookup, "m", toI, arr(toC, C.newInvokeSpecialMH(), toC, flagSer));
|
||||
mfSucceed(C.lookup, "m", toI, cToVoid, C.invokeInterfaceMH(), cToVoid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user