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