许多字节码指令,如xLoad,xAdd,xReturn,依赖于它们应用的类型。Type类提供了getOpcode方法,获取这些指令。该方法接受一个int类型的opCode作为参数,返回对应的类型对应的opcode。例如,如果t等于Type.FLOAT_TYPE,t.getOpcode(IMUL)返回FMUL。
// class version 49.0 (49) // access flags 49 public final class java/lang/Void { // access flags 25 // signature Ljava/lang/Class<Ljava/lang/Void;>; // declaration: java.lang.Class<java.lang.Void> public final static Ljava/lang/Class; TYPE // access flags 2 private <init>()V ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1 // access flags 8 static <clinit>()V LDC "void" INVOKESTATIC java/lang/Class.getPrimitiveClass (...)... PUTSTATIC java/lang/Void.TYPE : Ljava/lang/Class; RETURN MAXSTACK = 1 MAXLOCALS = 0 }
上面展示如何生成静态块static{},名义上使用<clinit>方法。注意,如果想跟踪chain中的某个class的单个方法的内容,使用TraceMethodVisitor,而不是TraceClassVisitor。
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); if (debug && mv != null && ...) { // if this method must be traced Printer p = new Textifier(ASM4) { @Override public void visitMethodEnd() { print(aPrintWriter ); // print it after it has been visited } }; mv = new TraceMethodVisitor(mv, p); } return new MyMethodAdapter (mv); }该段代码通过MyMethodAdapter转换后打印方法。
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); if (debug && mv != null && ...) { // if this method must be checked mv = new CheckMethodAdapter(mv); } return new MyMethodAdapter (mv); }这段代码检测MyMethodAdapter正确使用MethodVisitor API。然而该适配器不会检查字节码的正确与否。例如它不会探测ISTORE 1 ALOALD 1是否有效。事实上,如果使用CheckMethodAdapter的构造器,且在visitMaxs中提供有效的maxStack和maxLocals,这种错误可以被检测到。