asm[dynamically produce a class and use it without writing it to disk]

Suppose we want to use the ASM invocations to produce the very simple class:

public class Chocalate {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
       System.out.println("helloworld");
    }

}




It is basically a two-step task.

First step: use the bytecode plugin to view what asm code should be produced for such java code.



Second step, package the asm code and run them using the classloader:

add these code to the bottom of the dump() method. Dump returns the bytecode sequence for a class, it can be directly written into a class file using the FileOutputStream.

Also, we can directly use the class without storing it to the disk as follows.

byte[] code =cw.toByteArray();;
ChocalateDump loader = new ChocalateDump();// the class extends the Classloader, so that we can use the "protected" defineClass method to load the class just generated.
Class<?> exampleClass = loader.defineClass("Chocalate", code, 0, code.length);// load the class
exampleClass.getMethods()[0].invoke(null, new Object[] { null });

// this uses the reflection to invoke the main method.



That is all, the console will print "helloworld" as what the original Chocalate class did.

From the above process, we know we can generate asm code even without understanding the very details inside. All we need to is write an equivalent java code and ask plugin for the proper asm invocations.



For completeness, I also attach the ChocalateDump, i.e., the class containing the ASM invocations.

import java.util.*;
import org.objectweb.asm.*;
import org.objectweb.asm.attrs.*;
public class ChocalateDump extends ClassLoader implements Opcodes {

     public static void main(final String args[]) throws Exception {
         dump();
     }
public static byte[] dump () throws Exception {

ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;

cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Chocalate", null, "java/lang/Object", null);

cw.visitSource("Chocalate.java", null);

{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(2, l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(RETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "LChocalate;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(9, l0);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("helloworld");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLineNumber(10, l1);
mv.visitInsn(RETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l2, 0);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw.visitEnd();

byte[] code =cw.toByteArray();;
ChocalateDump loader = new ChocalateDump();
Class<?> exampleClass = loader.defineClass("Chocalate", code, 0, code.length);

exampleClass.getMethods()[0].invoke(null, new Object[] { null });

return cw.toByteArray();
}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值