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.implClass = implInfo.getDeclaringClass();
|
||||||
this.implIsInstanceMethod = true;
|
this.implIsInstanceMethod = true;
|
||||||
|
|
||||||
// Classes compiled prior to dynamic nestmate support invokes a private instance
|
// Classes compiled prior to dynamic nestmate support invoke a private instance
|
||||||
// method with REF_invokeSpecial.
|
// method with REF_invokeSpecial. Newer classes use REF_invokeVirtual or
|
||||||
//
|
// REF_invokeInterface, and we can use that instruction in the lambda class.
|
||||||
// invokespecial should only be used to invoke private nestmate constructors.
|
if (targetClass == implClass) {
|
||||||
// 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>")) {
|
|
||||||
this.implKind = implClass.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
|
this.implKind = implClass.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
|
||||||
} else {
|
} else {
|
||||||
this.implKind = REF_invokeSpecial;
|
this.implKind = REF_invokeSpecial;
|
||||||
|
@ -180,8 +180,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||||||
implMethodDesc = implInfo.getMethodType().toMethodDescriptorString();
|
implMethodDesc = implInfo.getMethodType().toMethodDescriptorString();
|
||||||
constructorType = factoryType.changeReturnType(Void.TYPE);
|
constructorType = factoryType.changeReturnType(Void.TYPE);
|
||||||
lambdaClassName = lambdaClassName(targetClass);
|
lambdaClassName = lambdaClassName(targetClass);
|
||||||
useImplMethodHandle = !Modifier.isPublic(implInfo.getModifiers()) &&
|
// If the target class invokes a protected method inherited from a
|
||||||
!VerifyAccess.isSamePackage(implClass, implInfo.getDeclaringClass());
|
// 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);
|
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||||
int parameterCount = factoryType.parameterCount();
|
int parameterCount = factoryType.parameterCount();
|
||||||
if (parameterCount > 0) {
|
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
|
// this class is linked at the indy callsite; so define a hidden nestmate
|
||||||
Lookup lookup;
|
Lookup lookup;
|
||||||
if (useImplMethodHandle) {
|
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,
|
lookup = caller.defineHiddenClassWithClassData(classBytes, implementation, !disableEagerInitialization,
|
||||||
NESTMATE, STRONG);
|
NESTMATE, STRONG);
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,9 +153,8 @@ public class MetafactoryArgValidationTest {
|
|||||||
amfSucceed(C.lookup, "m", toI, arr(cToVoid, C.invokeVirtualMH(), cToVoid, flagSer));
|
amfSucceed(C.lookup, "m", toI, arr(cToVoid, C.invokeVirtualMH(), cToVoid, flagSer));
|
||||||
mfSucceed(C.lookup, "m", toI, toVoid, C.invokeStaticMH(), toVoid);
|
mfSucceed(C.lookup, "m", toI, toVoid, C.invokeStaticMH(), toVoid);
|
||||||
amfSucceed(C.lookup, "m", toI, arr(toVoid, C.invokeStaticMH(), toVoid, flagSer));
|
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);
|
||||||
//mfSucceed(C.lookup, "m", toI, cToString, C.invokeSpecialMH(), cToString);
|
amfSucceed(C.lookup, "m", toI, arr(cToString, C.invokeSpecialMH(), cToString, flagSer));
|
||||||
//amfSucceed(C.lookup, "m", toI, arr(cToString, C.invokeSpecialMH(), cToString, flagSer));
|
|
||||||
mfSucceed(C.lookup, "m", toI, toC, C.newInvokeSpecialMH(), toC);
|
mfSucceed(C.lookup, "m", toI, toC, C.newInvokeSpecialMH(), toC);
|
||||||
amfSucceed(C.lookup, "m", toI, arr(toC, C.newInvokeSpecialMH(), toC, flagSer));
|
amfSucceed(C.lookup, "m", toI, arr(toC, C.newInvokeSpecialMH(), toC, flagSer));
|
||||||
mfSucceed(C.lookup, "m", toI, cToVoid, C.invokeInterfaceMH(), cToVoid);
|
mfSucceed(C.lookup, "m", toI, cToVoid, C.invokeInterfaceMH(), cToVoid);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user