Skip to content

Commit

Permalink
8268192: LambdaMetafactory with invokespecial causes VerificationError
Browse files Browse the repository at this point in the history
Reviewed-by: psandoz, mchung
  • Loading branch information
Dan Smith committed Jun 9, 2021
1 parent b41f3f8 commit 58ba48b
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 20 deletions.
Expand Up @@ -154,14 +154,10 @@
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;
Expand Down
Expand Up @@ -180,8 +180,15 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
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) {
Expand Down Expand Up @@ -394,13 +401,6 @@ public Void run() {
// 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 {
Expand Down
Expand Up @@ -153,9 +153,8 @@ public static void testLCE() {
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);
Expand Down

1 comment on commit 58ba48b

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.