< prev index next >
src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com
@@ -49,10 +49,11 @@
* public static void main(String[] args) {
* JJ<Integer> iii = (new CC())::impl;
* System.out.printf(">>> %s\n", iii.foo(44));
* }}
*/
+ final MethodHandles.Lookup caller;
final Class<?> targetClass; // The class calling the meta-factory via invokedynamic "class X"
final MethodType invokedType; // The type of the invoked method "(CC)II"
final Class<?> samBase; // The type of the returned instance "interface JJ"
final String samMethodName; // Name of the SAM method "foo"
final MethodType samMethodType; // Type of the SAM method "(Object)Object"
@@ -118,10 +119,11 @@
if ((caller.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
throw new LambdaConversionException(String.format(
"Invalid caller: %s",
caller.lookupClass().getName()));
}
+ this.caller = caller;
this.targetClass = caller.lookupClass();
this.invokedType = invokedType;
this.samBase = invokedType.returnType();
@@ -141,12 +143,24 @@
this.implIsInstanceMethod = true;
break;
case REF_invokeSpecial:
// JDK-8172817: should use referenced class here, but we don't know what it was
this.implClass = implInfo.getDeclaringClass();
- this.implKind = REF_invokeSpecial;
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>")) {
+ this.implKind = implClass.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
+ } else {
+ this.implKind = REF_invokeSpecial;
+ }
break;
case REF_invokeStatic:
case REF_newInvokeSpecial:
// JDK-8172817: should use referenced class here for invokestatic, but we don't know what it was
this.implClass = implInfo.getDeclaringClass();
< prev index next >