ASM 开发
IDEA使用插件 asm outline 查看 asm 如何生成该类。
类实现
对应的 asm 编程代码
package asm.com.javaedge.asm; import java.util.*; import org.objectweb.asm.*; public class TestAsmDump implements Opcodes { public static byte[] dump() throws Exception { ClassWriter cw = new ClassWriter(0); FieldVisitor fv; MethodVisitor mv; AnnotationVisitor av0; cw.visit(52, ACC_PUBLIC + ACC_SUPER, "com/javaedge/asm/TestAsm", null, "java/lang/Object", null); cw.visitSource("TestAsm.java", null); { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLineNumber(7, l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLocalVariable("this", "Lcom/javaedge/asm/TestAsm;", null, l0, l1, 0); mv.visitMaxs(1, 1); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "m", "()V", null, null); mv.visitCode(); Label l0 = new Label(); Label l1 = new Label(); Label l2 = new Label(); mv.visitTryCatchBlock(l0, l1, l2, "java/lang/InterruptedException"); Label l3 = new Label(); mv.visitLabel(l3); mv.visitLineNumber(10, l3); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("Hello ASM"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); mv.visitLabel(l0); mv.visitLineNumber(12, l0); mv.visitLdcInsn(new Long(100L)); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "sleep", "(J)V", false); mv.visitLabel(l1); mv.visitLineNumber(15, l1); Label l4 = new Label(); mv.visitJumpInsn(GOTO, l4); mv.visitLabel(l2); mv.visitLineNumber(13, l2); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/InterruptedException"}); mv.visitVarInsn(ASTORE, 1); Label l5 = new Label(); mv.visitLabel(l5); mv.visitLineNumber(14, l5); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/InterruptedException", "printStackTrace", "()V", false); mv.visitLabel(l4); mv.visitLineNumber(16, l4); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitInsn(RETURN); Label l6 = new Label(); mv.visitLabel(l6); mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l5, l4, 1); mv.visitLocalVariable("this", "Lcom/javaedge/asm/TestAsm;", null, l3, l6, 0); mv.visitMaxs(2, 2); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); } }
看看最简单的统计方法执行时间
... mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false); mv.visitVarInsn(LSTORE, 1); ... mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("Hello ASM"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); mv.visitLabel(l0); mv.visitLineNumber(13, l0); mv.visitLdcInsn(new Long(100L)); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "sleep", "(J)V", false); mv.visitLabel(l1); mv.visitLineNumber(16, l1); Label l5 = new Label(); mv.visitJumpInsn(GOTO, l5); mv.visitLabel(l2); mv.visitLineNumber(14, l2); mv.visitFrame(Opcodes.F_FULL, 2, new Object[]{"com/javaedge/asm/TestAsm", Opcodes.LONG}, 1, new Object[]{"java/lang/InterruptedException"}); mv.visitVarInsn(ASTORE, 3); Label l6 = new Label(); mv.visitLabel(l6); mv.visitLineNumber(15, l6); mv.visitVarInsn(ALOAD, 3); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/InterruptedException", "printStackTrace", "()V", false); mv.visitLabel(l5); mv.visitLineNumber(17, l5); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false); mv.visitVarInsn(LSTORE, 3); Label l7 = new Label(); mv.visitLabel(l7); mv.visitLineNumber(18, l7); 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", false); mv.visitLdcInsn("m\u65b9\u6cd5\u6267\u884c\u65f6\u95f4: "); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitVarInsn(LLOAD, 3); mv.visitVarInsn(LLOAD, 1); mv.visitInsn(LSUB); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); Label l8 = new Label(); mv.visitLabel(l8); mv.visitLineNumber(19, l8); mv.visitInsn(RETURN); Label l9 = new Label(); mv.visitLabel(l9); mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l6, l5, 3); mv.visitLocalVariable("this", "Lcom/javaedge/asm/TestAsm;", null, l3, l9, 0); mv.visitLocalVariable("start", "J", null, l4, l9, 1); mv.visitLocalVariable("end", "J", null, l7, l9, 3); mv.visitMaxs(6, 5); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); } }
这样我们就知道之后用 ASM 编程该加哪些代码了。