rt/vm/src/test/java/org/apidesign/vm4brwsr/InvokeDynamicTest.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 09 Aug 2014 10:42:22 +0200
branchjdk8
changeset 1644 d02324a82d80
child 1645 0101d10bd2e0
permissions -rw-r--r--
A way to test invokeDynamic on JDK7 inspired by https://code.google.com/p/indy-maven-plugin/
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.vm4brwsr;
    19 
    20 import java.io.InputStream;
    21 import java.lang.invoke.CallSite;
    22 import java.lang.invoke.MethodHandles;
    23 import java.lang.invoke.MethodType;
    24 import java.lang.reflect.Method;
    25 import org.objectweb.asm.ClassReader;
    26 import org.objectweb.asm.ClassVisitor;
    27 import org.objectweb.asm.ClassWriter;
    28 import org.objectweb.asm.Handle;
    29 import org.objectweb.asm.MethodVisitor;
    30 import org.objectweb.asm.Opcodes;
    31 import static org.objectweb.asm.Opcodes.ASM4;
    32 import static org.objectweb.asm.Opcodes.INVOKESTATIC;
    33 import static org.testng.Assert.*;
    34 import org.testng.annotations.BeforeClass;
    35 import org.testng.annotations.Test;
    36 
    37 /**
    38  *
    39  * @author Jaroslav Tulach <jtulach@netbeans.org>
    40  */
    41 public class InvokeDynamicTest {
    42     private static Class<?> invokeDynamicClass;
    43     
    44     @Test public void simpleDynamicInJava() throws Exception {
    45         Method m = invokeDynamicClass.getMethod("dynamicSay");
    46         Object ret = m.invoke(m);
    47         assertEquals(ret, "Hello from Dynamic!");
    48     }
    49     
    50     
    51 /*    
    52     private static TestVM code;
    53 
    54     @BeforeClass
    55     public void compileTheCode() throws Exception {
    56         code = TestVM.compileClass(InvokeDynamic.class.getName());
    57     }
    58 
    59     @AfterClass
    60     public static void releaseTheCode() {
    61         code = null;
    62     }
    63 
    64     private void assertExec(
    65             String msg, Class clazz, String method, Object expRes, Object... args
    66     ) throws Exception {
    67         code.assertExec(msg, clazz, method, expRes, args);
    68     }
    69  */
    70 
    71     //
    72     // the following code is inspired by 
    73     // https://code.google.com/p/indy-maven-plugin/
    74     // which I don't want to use, as it is not in a public repository
    75     //
    76     @BeforeClass 
    77     public static void prepareClass() throws Exception {
    78         InputStream input = InvokeDynamic.class.getResourceAsStream("InvokeDynamic.class");
    79         assertNotNull(input, "Class found");
    80         
    81         ClassReader reader = new ClassReader(input);
    82         ClassWriter writer = new ClassWriter(reader, 0);
    83 
    84         reader.accept(
    85                 new ClassVisitor(ASM4, writer) {
    86                     @Override
    87                     public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions
    88                     ) {
    89                         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    90                         return new InvokeDynamicProcessor(mv);
    91                     }
    92                 },
    93                 0);
    94         input.close();
    95         final byte[] invokeDynamicBytes = writer.toByteArray();
    96         ClassLoader l = new ClassLoader() {
    97             @Override
    98             public Class<?> loadClass(String name) throws ClassNotFoundException {
    99                 if (name.equals(InvokeDynamic.class.getName())) {
   100                     return defineClass(name, invokeDynamicBytes, 0, invokeDynamicBytes.length);
   101                 }
   102                 return super.loadClass(name);
   103             }
   104         };
   105         invokeDynamicClass = l.loadClass(InvokeDynamic.class.getName());
   106     }
   107     
   108     
   109     private static class InvokeDynamicProcessor extends MethodVisitor {
   110         InvokeDynamicProcessor(MethodVisitor mv) {
   111             super(ASM4, mv);
   112         }
   113 
   114         @Override
   115         public void visitMethodInsn(int opcode, String owner, String name, String desc) {
   116             if (opcode == INVOKESTATIC) {
   117                 if (name.startsWith("TEST_dynamic_")) {
   118                     final String shortName = name.substring(13);
   119                     Handle mh = new Handle(
   120                         Opcodes.H_INVOKESTATIC, owner, shortName,
   121                         MethodType.methodType(
   122                             CallSite.class,
   123                             MethodHandles.Lookup.class,
   124                             String.class, 
   125                             MethodType.class
   126                         ).toMethodDescriptorString()
   127                     );
   128                     super.visitInvokeDynamicInsn(shortName, desc, mh);
   129                     return;
   130                 }
   131             }
   132             super.visitMethodInsn(opcode, owner, name, desc);
   133         }
   134     }
   135     
   136     
   137 }