Lookup.defineAnonymousClass() vs indy

Mandy Chung mandy.chung at oracle.com
Mon Nov 30 18:16:25 UTC 2020


The implementation method to be invoked for this lambda is a static bridge method
taking this hidden class's instance as the parameter, i.e. a descriptor referencing
a hidden class, which will fail to resolve.


  0: #104 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     Method arguments:
       #111 ()V
       #112 REF_invokeStatic HiddenClassWithIndy.lambda$test$0:(LHiddenClassWithIndy;)V
       #111 ()V


Now that a hidden class is a nestmate, should/can this bridge method be 
an instance method if this class is defined as a hidden class?

Mandy

On 11/29/20 7:34 AM, Remi Forax wrote:
> Hi Mandy, hi all,
> it seems that when defineAnonymousClass rewrites the currentClass, it doesn't work if there is an invokedynamic in the classfile, so defineHiddenClass fails with a VerifyError when the hidden class is verified.
>
> Here is an example showing the issue
> ---
> import java.io.IOException;
> import java.lang.invoke.MethodHandles;
>
> public class HiddenClassWithIndy {
>    public void test() {
>      var a = new HiddenClassWithIndy();
>      Runnable r = () -> System.out.println(a);
>    }
>
>    public static void main(String[] args) throws IOException, IllegalAccessException {
>      byte[] bytecode;
>      try(var input = HiddenClassWithIndy.class.getClassLoader().getResourceAsStream(HiddenClassWithIndy.class.getName().replace('.', '/') + ".class")) {
>        if (input == null) {
>          throw new AssertionError();
>        }
>        bytecode = input.readAllBytes();
>      }
>      var hiddenLookup = MethodHandles.lookup().defineHiddenClass(bytecode, true);
>    }
> }
>
> ---
> The error message:
> Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
> Exception Details:
>    Location:
>      fr/umlv/transmogrif/HiddenClassWithIndy+0x0000000801002400.test()V @9: invokedynamic
>    Reason:
>      Type 'fr/umlv/transmogrif/HiddenClassWithIndy+0x0000000801002400' (current frame, stack[0]) is not assignable to 'fr/umlv/transmogrif/HiddenClassWithIndy'
>    Current Frame:
>      bci: @9
>      flags: { }
>      locals: { 'fr/umlv/transmogrif/HiddenClassWithIndy+0x0000000801002400', 'fr/umlv/transmogrif/HiddenClassWithIndy+0x0000000801002400' }
>      stack: { 'fr/umlv/transmogrif/HiddenClassWithIndy+0x0000000801002400' }
>    Bytecode:
>      0000000: bb00 0759 b700 094c 2bba 000a 0000 4db1
>      0000010:
>
> 	at java.base/java.lang.ClassLoader.defineClass0(Native Method)
> 	at java.base/java.lang.System$2.defineClass(System.java:2193)
> 	at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2235)
> 	at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClassAsLookup(MethodHandles.java:2216)
> 	at java.base/java.lang.invoke.MethodHandles$Lookup.defineHiddenClass(MethodHandles.java:1952)
> 	at fr.umlv.transmogrif.HiddenClassWithIndy.main(HiddenClassWithIndy.java:20)
>
> regards,
> Rémi



More information about the core-libs-dev mailing list