Skip to content

Instantly share code, notes, and snippets.

@matthieu
Created February 21, 2011 23:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthieu/837938 to your computer and use it in GitHub Desktop.
Save matthieu/837938 to your computer and use it in GitHub Desktop.
package dyn;
import org.objectweb.asm.*;
import org.objectweb.asm.util.TraceClassVisitor;
import sun.dyn.anon.AnonymousClassLoader;
import java.io.PrintWriter;
public class Indy implements Opcodes {
public static void main(String[] args) {
MyCL myCL = new MyCL();
Class caller = myCL.defineClass("Caller", makeCaller());
try {
caller.getMethod("foo").invoke(caller.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
public static class MyCL extends ClassLoader {
public Class defineClass(String name, byte[] code) {
return defineClass(name, code, 0, code.length);
}
}
public static byte[] makeCaller() {
ClassWriter cv = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
TraceClassVisitor cw = new TraceClassVisitor(cv, new PrintWriter(System.out));
MethodVisitor mv;
cw.visit(51, ACC_PUBLIC+ACC_SUPER, "Caller", null, "dyn/Invoker", null);
cw.visitField(ACC_PUBLIC, "callee", "Ljava/lang/Class;", null, null).visitEnd();
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "dyn/Invoker", "<init>", "()V");
mv.visitVarInsn(ALOAD, 0);
mv.visitTypeInsn(NEW, "sun/dyn/anon/AnonymousClassLoader");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "sun/dyn/anon/AnonymousClassLoader", "<init>", "()V");
mv.visitMethodInsn(INVOKESTATIC, "dyn/Indy", "makeCallee", "()[B");
mv.visitMethodInsn(INVOKEVIRTUAL, "sun/dyn/anon/AnonymousClassLoader", "loadClass", "([B)Ljava/lang/Class;");
mv.visitFieldInsn(PUTFIELD, "Caller", "callee", "Ljava/lang/Class;");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "foo", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, "Caller", "callee", "Ljava/lang/Class;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "newInstance", "()Ljava/lang/Object;");
mv.visitFieldInsn(PUTFIELD, "Caller", "targetObject", "Ljava/lang/Object;");
mv.visitLdcInsn("cde");
mv.visitInvokeDynamicInsn("my:stuff", "(Ljava/lang/String;)V",
new MethodHandle(MH_INVOKEVIRTUAL, "Caller", "bootstrap",
new MethodType(Invoker.class.getMethods()[0]).getDescriptor()));
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
cw.visitEnd();
return cv.toByteArray();
}
public static byte[] makeCallee() {
ClassWriter cv = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
TraceClassVisitor cw = new TraceClassVisitor(cv, new PrintWriter(System.out));
MethodVisitor mv;
cw.visit(51, ACC_PUBLIC, "Callee", null, "java/lang/Object", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "bar", "(Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
mv.visitLdcInsn("in bar ");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
cw.visitEnd();
return cv.toByteArray();
}
}
package dyn;
import java.dyn.*;
public class Invoker {
protected Object targetObject;
public CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
try {
MethodHandle handle = lookup.bind(targetObject, "bar",
MethodType.methodType(void.class, String.class));
return new ConstantCallSite(handle);
} catch (NoAccessException e) {
throw new RuntimeException("Failed lookup", e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment