java asm 读取虚拟机_利用ASM读取class

我们都知道在计算机中通过控制器识别机器指令来进行工作,而不同的操作系统其机器指令集不尽相同,为了屏蔽不同操作系统之间机器指令之间的差异,java引入java虚拟机,通过编译器编译的.java文件会转换成.class的字节码文件,而不同操作系统的java虚拟机将字节码文件解释成对应的机器指令来执行。由此看来,java虚拟机并不认识.java文件,只能识别class文件,只要字节码文件是正确的就行。但是一般人还是写不来字节码文件的,我们打开一个字节码文件我们就知道其都是16进制数,并且字节码文件的写法有严格的要求。正因为字节码文件有着严格的结构,我们就可以利用它来写出标准的解析方法,甚至是生成我们指定的class类。ASM通过将这些解析和生成的方法封装,通过更加人性化的方法调用给我们提供供了解析和生成class类的方法。

ASM的范围:

The goal of the ASM library is to generate, transform and analyze compiled

Java classes, represented as byte arrays (as they are stored on disk and loaded

in the Java Virtual Machine). For this purpose ASM provides tools to read,

write and transform such byte arrays by using higher level concepts than bytes,

such as numeric constants, strings, Java identifiers, Java types, Java class

structure elements, etc. Note that the scope of the ASM library is strictly

limited to reading, writing, transforming and analyzing classes. In particular

the class loading process is out of scope.

ASM库的目标是生成、转换和分析编译后的Java类,这些类表示为字节数组(因为它

们存储在磁盘上,并加载在Java虚拟机中)。为此,ASM提供了一些工具,通过使用

比字节更高级别的概念(如数字常量、字符串、Java标识符、Java类型、Java类结构

元素等)来读取、写入和转换这样的字节数组。请注意,ASM库的范围严格限制于

读、写、转换和分析类。特别是类加载过程超出了范围。

the ASM name does not mean anything: it is just a reference to the __asm__ keyword in

C, which allows some functions to be implemented in assembly language.

ASM名称没有任何意义:它只是一个对……asm__关键字in的引用

它允许用汇编语言实现一些函数。

ASM库提供了两个api来生成和转换编译后的api类:

核心API提供了基于事件的类表示:基于事件的模型用一系列事件来表示类

tree API提供了一个基于对象的表示:基于对象的模型每个类都用对象树表示。

优缺点:

基于事件的API比基于对象的API更快,需要的内存更少,因为不需要在内存中创建和存储表示类的对象树(SAX和DOM之间也存在相同的差异)。

然而,使用基于事件的API实现类转换可能更加困难,因为在任何给定的时间内,该类中只有一个元素可用(对应于当前事件的元素),而使用基于对象的API,整个类在内存中可用。

Core API:

最主要的三个APIClassVistor,ClassReader,ClassWriter.

ClassReader类解析作为字节数组给出的编译类,并在ClassVisitor上调用相visitXxx方法实例作为参数传递给它的accept方法。它可以被看作是一个事件生成器。

ClassWriter类是ClassVisitor抽象类的子类,它直接以二进制形式构建编译后的类。它产生的输出一个字节数组,其中包含可检索的已编译类使用toByteArray方法。它可以被视为事件消费者。

ClassVisitor类将它接收到的所有方法调用委托给另一个ClassVisitor实例。它可以看作是一个事件过滤器。

实例:(加载类信息并打印出来)

下面来门来通过一个简单的例子实现访问一个类,并打印出类的信息,这里主要通过CLassVisitor方法。我们继承ClassVisitor抽象类,并且重写里面的方法,前面已经提到了,CLassVisitor中一个方法就是描述一个类的信息。我们重写里面的方法将类的信息打印处理。我们将这些具体的行为封装在一哥类中,并把它交给CLassReader的accpet方法,accept方法会通过CLassVisitor中的方法完成具体的动作。这里用到了命令模式,将调用的方法封装起来,通过参数的形式传递。

class ClassPrinter extends ClassVisitor {

public ClassPrinter() {

super(Opcodes.ASM4);

}

public void visit(int version, int access, String name,

String signature, String superName, String[] interfaces) {

System.out.println(name + " extends " + superName + " {");

}

public void visitSource(String source, String debug) {

}

public void visitOuterClass(String owner, String name, String desc) {

}

public AnnotationVisitor visitAnnotation(String desc,

boolean visible) {

return null;

}

public void visitAttribute(Attribute attr) {

}

public void visitInnerClass(String name, String outerName,

String innerName, int access) {

}

public FieldVisitor visitField(int access, String name, String desc,

String signature, Object value) {

System.out.println(" " + desc + " " + name);

return null;

}

public MethodVisitor visitMethod(int access, String name,

String desc, String signature, String[] exceptions) {

System.out.println(" " + name + desc);

return null;

}

public void visitEnd() {

System.out.println("}");

}

}

现在我们需要将ClassVisitor传递给CLassReader的accept方法。ClassReader负责两指定的加载。

ClassPrinter cp = new ClassPrinter();

ClassReader cr = new ClassReader("java.lang.Object");

cr.accept(cp, 0);

运行结果:

java/lang/Object extends null {

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值