A way to test invokeDynamic on JDK7 inspired by https://code.google.com/p/indy-maven-plugin/ jdk8
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 09 Aug 2014 10:42:22 +0200
branchjdk8
changeset 1644d02324a82d80
parent 1642 c178e0bdce5d
child 1645 0101d10bd2e0
A way to test invokeDynamic on JDK7 inspired by https://code.google.com/p/indy-maven-plugin/
rt/vm/src/test/java/org/apidesign/vm4brwsr/InvokeDynamic.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/InvokeDynamicTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/InvokeDynamic.java	Sat Aug 09 10:42:22 2014 +0200
     1.3 @@ -0,0 +1,46 @@
     1.4 +/**
     1.5 + * Back 2 Browser Bytecode Translator
     1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, version 2 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program. Look for COPYING file in the top folder.
    1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    1.20 + */
    1.21 +package org.apidesign.vm4brwsr;
    1.22 +
    1.23 +import java.lang.invoke.CallSite;
    1.24 +import java.lang.invoke.ConstantCallSite;
    1.25 +import java.lang.invoke.MethodHandles;
    1.26 +import java.lang.invoke.MethodType;
    1.27 +
    1.28 +public class InvokeDynamic {
    1.29 +
    1.30 +    public static String dynamicSay() {
    1.31 +        return TEST_dynamic_boot1(new InvokeDynamic());
    1.32 +    }
    1.33 +
    1.34 +    private static String TEST_dynamic_boot1(InvokeDynamic instance) {
    1.35 +        throw new IllegalStateException("Can't touch this");
    1.36 +    }
    1.37 +
    1.38 +    public static CallSite boot1(MethodHandles.Lookup lookup, String name, MethodType type) {
    1.39 +        try {
    1.40 +            return new ConstantCallSite(lookup.findVirtual(InvokeDynamic.class, "instance_sayHello", MethodType.methodType(String.class)));
    1.41 +        } catch (NoSuchMethodException | IllegalAccessException e) {
    1.42 +            throw new IllegalStateException(e);
    1.43 +        }
    1.44 +    }
    1.45 +
    1.46 +    public String instance_sayHello() {
    1.47 +        return "Hello from Dynamic!";
    1.48 +    }
    1.49 +}
    1.50 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/InvokeDynamicTest.java	Sat Aug 09 10:42:22 2014 +0200
     2.3 @@ -0,0 +1,137 @@
     2.4 +/**
     2.5 + * Back 2 Browser Bytecode Translator
     2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, version 2 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program. Look for COPYING file in the top folder.
    2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    2.20 + */
    2.21 +package org.apidesign.vm4brwsr;
    2.22 +
    2.23 +import java.io.InputStream;
    2.24 +import java.lang.invoke.CallSite;
    2.25 +import java.lang.invoke.MethodHandles;
    2.26 +import java.lang.invoke.MethodType;
    2.27 +import java.lang.reflect.Method;
    2.28 +import org.objectweb.asm.ClassReader;
    2.29 +import org.objectweb.asm.ClassVisitor;
    2.30 +import org.objectweb.asm.ClassWriter;
    2.31 +import org.objectweb.asm.Handle;
    2.32 +import org.objectweb.asm.MethodVisitor;
    2.33 +import org.objectweb.asm.Opcodes;
    2.34 +import static org.objectweb.asm.Opcodes.ASM4;
    2.35 +import static org.objectweb.asm.Opcodes.INVOKESTATIC;
    2.36 +import static org.testng.Assert.*;
    2.37 +import org.testng.annotations.BeforeClass;
    2.38 +import org.testng.annotations.Test;
    2.39 +
    2.40 +/**
    2.41 + *
    2.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.43 + */
    2.44 +public class InvokeDynamicTest {
    2.45 +    private static Class<?> invokeDynamicClass;
    2.46 +    
    2.47 +    @Test public void simpleDynamicInJava() throws Exception {
    2.48 +        Method m = invokeDynamicClass.getMethod("dynamicSay");
    2.49 +        Object ret = m.invoke(m);
    2.50 +        assertEquals(ret, "Hello from Dynamic!");
    2.51 +    }
    2.52 +    
    2.53 +    
    2.54 +/*    
    2.55 +    private static TestVM code;
    2.56 +
    2.57 +    @BeforeClass
    2.58 +    public void compileTheCode() throws Exception {
    2.59 +        code = TestVM.compileClass(InvokeDynamic.class.getName());
    2.60 +    }
    2.61 +
    2.62 +    @AfterClass
    2.63 +    public static void releaseTheCode() {
    2.64 +        code = null;
    2.65 +    }
    2.66 +
    2.67 +    private void assertExec(
    2.68 +            String msg, Class clazz, String method, Object expRes, Object... args
    2.69 +    ) throws Exception {
    2.70 +        code.assertExec(msg, clazz, method, expRes, args);
    2.71 +    }
    2.72 + */
    2.73 +
    2.74 +    //
    2.75 +    // the following code is inspired by 
    2.76 +    // https://code.google.com/p/indy-maven-plugin/
    2.77 +    // which I don't want to use, as it is not in a public repository
    2.78 +    //
    2.79 +    @BeforeClass 
    2.80 +    public static void prepareClass() throws Exception {
    2.81 +        InputStream input = InvokeDynamic.class.getResourceAsStream("InvokeDynamic.class");
    2.82 +        assertNotNull(input, "Class found");
    2.83 +        
    2.84 +        ClassReader reader = new ClassReader(input);
    2.85 +        ClassWriter writer = new ClassWriter(reader, 0);
    2.86 +
    2.87 +        reader.accept(
    2.88 +                new ClassVisitor(ASM4, writer) {
    2.89 +                    @Override
    2.90 +                    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions
    2.91 +                    ) {
    2.92 +                        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    2.93 +                        return new InvokeDynamicProcessor(mv);
    2.94 +                    }
    2.95 +                },
    2.96 +                0);
    2.97 +        input.close();
    2.98 +        final byte[] invokeDynamicBytes = writer.toByteArray();
    2.99 +        ClassLoader l = new ClassLoader() {
   2.100 +            @Override
   2.101 +            public Class<?> loadClass(String name) throws ClassNotFoundException {
   2.102 +                if (name.equals(InvokeDynamic.class.getName())) {
   2.103 +                    return defineClass(name, invokeDynamicBytes, 0, invokeDynamicBytes.length);
   2.104 +                }
   2.105 +                return super.loadClass(name);
   2.106 +            }
   2.107 +        };
   2.108 +        invokeDynamicClass = l.loadClass(InvokeDynamic.class.getName());
   2.109 +    }
   2.110 +    
   2.111 +    
   2.112 +    private static class InvokeDynamicProcessor extends MethodVisitor {
   2.113 +        InvokeDynamicProcessor(MethodVisitor mv) {
   2.114 +            super(ASM4, mv);
   2.115 +        }
   2.116 +
   2.117 +        @Override
   2.118 +        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
   2.119 +            if (opcode == INVOKESTATIC) {
   2.120 +                if (name.startsWith("TEST_dynamic_")) {
   2.121 +                    final String shortName = name.substring(13);
   2.122 +                    Handle mh = new Handle(
   2.123 +                        Opcodes.H_INVOKESTATIC, owner, shortName,
   2.124 +                        MethodType.methodType(
   2.125 +                            CallSite.class,
   2.126 +                            MethodHandles.Lookup.class,
   2.127 +                            String.class, 
   2.128 +                            MethodType.class
   2.129 +                        ).toMethodDescriptorString()
   2.130 +                    );
   2.131 +                    super.visitInvokeDynamicInsn(shortName, desc, mh);
   2.132 +                    return;
   2.133 +                }
   2.134 +            }
   2.135 +            super.visitMethodInsn(opcode, owner, name, desc);
   2.136 +        }
   2.137 +    }
   2.138 +    
   2.139 +    
   2.140 +}