Package com.java7developer.chapter5

Source Code of com.java7developer.chapter5.DynamicIndyMaker

package com.java7developer.chapter5;

// NOTE: This class requires the ASM library - version 4 RC1 or above.

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.math.BigDecimal;

import static org.objectweb.asm.Opcodes.*;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

public class DynamicIndyMaker {
  private volatile int ID_GENERATOR = 0;

  public void makeClassWithInvokeDynamic(String nameOfIndyCallsite,
      MethodType desc, Class<?> bsmClass, String bsmName, MethodType bsmType,
      Object... bsmArgs) {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    String clazzName = "Gen" + (ID_GENERATOR++);
    cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, clazzName, null, "java/lang/Object",
        null);

    MethodVisitor init = cw
        .visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    init.visitCode();
    init.visitVarInsn(ALOAD, 0);
    init.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    init.visitInsn(RETURN);
    init.visitMaxs(-1, -1);
    init.visitEnd();

    String descriptor = desc.toMethodDescriptorString();

    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invokedynamic",
        descriptor, null, null);
    // MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "invokedynamic",
    // descriptor, null, null);
    int slot = 0;
    for (Type parameterType : Type.getArgumentTypes(descriptor)) {
      mv.visitVarInsn(parameterType.getOpcode(ILOAD), slot);
      slot += parameterType.getSize();
    }

    // 1st 2 args are name and descriptor of this indy callsite
    mv.visitInvokeDynamicInsn(nameOfIndyCallsite, descriptor,
        new Handle(H_INVOKESTATIC, bsmClass.getName().replace('.', '/'),
            bsmName, bsmType.toMethodDescriptorString()), bsmArgs);

    Type returnType = Type.getReturnType(descriptor);
    mv.visitInsn(returnType.getOpcode(IRETURN));

    mv.visitMaxs(-1, -1);
    mv.visitEnd();

    cw.visitEnd();

    byte[] bytes = cw.toByteArray();
    // Class<?> clazz = defineClass(null, bytes, 0, bytes.length);

    /*
     * try (FileOutputStream fos = new FileOutputStream(clazzName + ".class")) {
     * fos.write(bytes); }
     */

    try {
      FileOutputStream fos = new FileOutputStream(clazzName + ".class");
      fos.write(bytes);
    } catch (IOException iox) {
      iox.printStackTrace();
    }

    /*
     * try { return MethodHandles.lookup().findStatic(clazz, "invokedynamic",
     * desc); // return MethodHandles.lookup().findVirtual(clazz,
     * "invokedynamic", desc); } catch (NoAccessException e) { throw
     * (AssertionError)new AssertionError().initCause(e); }
     */
  }

  // Bootstrap method, has to be static and return a callsite
  public static CallSite bsm(Lookup lookup, String name, MethodType methodType,
      Object arg) {
    System.out.println("construct the BigDecimal constant " + arg);

    // return a trivial constant callsite, with a constant method handle as its
    // target
    return new ConstantCallSite(MethodHandles.constant(BigDecimal.class,
        new BigDecimal(arg.toString())));
  }

  public static void main(String[] args) throws Throwable {
    DynamicIndyMaker indyMaker = new DynamicIndyMaker();
    // indyMaker.makeClassWithInvokeDynamic(nameOfCallSite, desc, bsmClass,
    // bsmName, bsmType, bsmArgs)

    indyMaker.makeClassWithInvokeDynamic("_", MethodType
        .methodType(BigDecimal.class), DynamicIndyMaker.class, "bsm",
        MethodType.methodType(CallSite.class, Lookup.class, String.class,
            MethodType.class, Object.class), "1234567890.1234567890");

  }

}
TOP

Related Classes of com.java7developer.chapter5.DynamicIndyMaker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.