ASM指南翻译-7
2.3工具
public abstract compareTo(Ljava/lang/Object;)I
}
注意,为了弄清楚在转换链中到底发生了什么,你可以在生成类或者转换链过程的任何点使用TraceClassVisitor,而不仅仅是在ClassWriter之前使用。注意,通过这个类生成的类的文本表示可以通过String.equals()很容易地进行比较。
?
2.3.3 CheckClassAdapter
ClassWriter并不会检查它的方法调用是否按照合适的顺序以及参数是否有效。这样就可能生成无效的代码,而被java虚拟机的验证工具所拒绝。为了尽可能地检测出这些错误,可以使用CheckClassAdapter。和TraceClassVisitor一样,这个类也实现了ClassVisitor接口,它也会将对它的方法调用委托给其他的ClassVisitor,例如一个TraceClassVisitor或者ClassWriter。尽管如此,除了打印类的文本表示,这个类会在将方法调用委托给下一个ClassVisitor之前,检查对它的方法调用顺序是否合理,以及参数是否有效。如果发生错误,将会抛出IllegalStateException或者IllegalArgumentException。
?
为了检查一个类,并且打印它的文本表示,最终创建一个字节数组,你可以参考下面的代码:
ClassWriter cw = new ClassWriter(0);
TraceClassVisitor tcv = newTraceClassVisitor(cw, printWriter);
CheckClassAdapter cv = newCheckClassAdapter(tcv);
cv.visit(...);
...
cv.visitEnd();
byte b[] = cw.toByteArray();
?
注意,如果这些ClassVisitor的顺序不同,那么它们会以不同的顺序执行。例如,下面的代码会导致在跟踪代码以后再检查类。
ClassWriter cw = new ClassWriter(0);
CheckClassAdapter cca = newCheckClassAdapter(cw);
TraceClassVisitor cv = newTraceClassVisitor(cca, printWriter);
?
就像TraceClassVisitor一样,为了检查类是否有效,你也可以在生成类或者转换类的链的任何节点使用CheckClassAdapter,而不仅仅是在ClassWriter之前。
?
2.3.4 ASMifierClassVisitor
这个类也实现了ClassVisitor接口,它的每个方法会打印出调用它的java代码。例如,调用visitEnd会打印出cv.visitEnd();,结果是,当这个visitor解析一个类时,它会打印出使用ASM来生成这个类的源代码。当你使用这个类去解析一个存在的类时,你会发现它很有用。例如,如果你不知道如何使用ASM来生成一些编译后的类,那么你可以先写出这些类的源代码,然后使用javac来编译,再然后使用ASMifierClassVisitor来解析,这样就能够得到使用ASM来生成这些类的源代码了。
?
ASMifierClassVisitor可以通过命令行直接使用,如下面的例子:
java -classpath asm.jar:asm-util.jar \
???????? org.objectweb.asm.util.ASMifierClassVisitor\
???????? java.lang.Runnable
?
生成的代码经过缩进以后,就是下面的代码:
package asm.java.lang;
import org.objectweb.asm.*;
public class RunnableDump implementsOpcodes {
???????? publicstatic byte[] dump() throws Exception {
?????????????????? ClassWritercw = new ClassWriter(0);
?????????????????? FieldVisitorfv;
?????????????????? MethodVisitormv;
?????????????????? AnnotationVisitorav0;
?????????????????? cw.visit(V1_5,ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE,
??????????????????????????? "java/lang/Runnable",null, "java/lang/Object", null);
?????????????????? {
??????????????????????????? mv= cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "run", "()V",
???????????????????????????????????? null,null);
??????????????????????????? mv.visitEnd();
?????????????????? }
?????????????????? cw.visitEnd();
?????????????????? returncw.toByteArray();
???????? }
}