使用 ASM 从 .class 文件中提取类的详细信息

红薯 发布于 2010/03/29 13:52
阅读 3K+
收藏 5
ASM

ASM 是一个 Java 字节码操纵框架。它可以直接以二进制形式动态地生成 stub 类或其他代理类,或者在装载时动态地修改类。

今天我们提供一个简单例子用来掩饰 ASM 最基本的功能,解析 .class 文件的信息。ASM 提供了一个 ClassReader 类用来解析 class 文件,该类需要一个 ClassVisitor 接口的实例,使用类似事件的模式来触发这个实例。当解析一个类文件时,会严格依照下列顺序调用 ClassVisitor 的方法(请看下面源码):

package my.test.asm;

import java.io.IOException;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

/**
 * ASM测试
 * @author Winter Lau
 */
public class AsmTester {

	public final static float VERSION = 1.6f;
	
	public static void main(String[] args) throws IOException {
		testRead();
	}

	private static void testRead() throws IOException {
		ClassVisitor visitor = new ClassVisitor() {
			@Override
			public void visit(int version, int access, String name,
					String signature, String superName, String[] interfaces) {
				System.out.println(name + " extends " + superName + " {");
			}
			@Override
			public void visitSource(String source, String debug) {
			}
			@Override
			public void visitOuterClass(String owner, String name, String desc) {
			}
			@Override
			public AnnotationVisitor visitAnnotation(String desc, boolean visiable) {
				return null;
			}
			@Override
			public void visitAttribute(Attribute attr) {
			}
			@Override
			public void visitInnerClass(String name, String outerName,
					String innerName, int access) {
			}
			@Override
			public FieldVisitor visitField(int access, String name,
					String desc, String signature, Object value) {
				System.out.println(" " + desc + " " + name + "(" + value + ")");
				return null;
			}
			@Override
			public MethodVisitor visitMethod(int access, String name,
					String desc, String signature, String[] exceptions) {
				System.out.println(" " + name + desc);
				return null;
			}
			@Override
			public void visitEnd() {
				System.out.println("}");
			}

		};
		ClassReader cr = new ClassReader("my.test.asm.AsmTester");
		cr.accept(visitor, 0);
	}

}

该类执行结果如下:

my/test/asm/AsmTester extends java/lang/Object {
 F VERSION(1.6)
 <init>()V
 main([Ljava/lang/String;)V
 testRead()V
}

你可以将一个 .class 文件的字节流直接传递给 ClassReader 类,或者是通过 getResourceAsStream 来获取一个 .class 文件的流数据。

加载中
0
小黑小别姬
小黑小别姬

我怎么没找到 怎么设置class文件的package啊?

0
兰穆达
兰穆达

嗨,以为是汇编语言呢!

0
孟飞阳
孟飞阳
赞红薯。我用5.0.4代码测试时,发现Classvisitor方法非要输入一个int参数,加上这个参数就不会报错了:Opcodes.ASM5,或Opcodes.ASM4
返回顶部
顶部