ASM是非常强大的JAVA字节码生成和修改工具,具有性能优异、文档齐全、比较易用等优点。官方网站:http://asm.ow2.org/
要想熟练的使用ASM,需要对java字节码有一定的了解,本文重点对java函数的字节码进行介绍。本文部分内容参考官方文档:http://download.forge.objectweb.org/asm/asm4-guide.pdf
1.JAVA虚拟机执行模型
在JVM执行模型里,每个方法都是在线程中执行,而每个线程对应自己的栈,每个栈由帧组成。每个帧对应一个方法调用,每次调用一个方法,
会将新帧压入当前线程的执行栈,当方法返回时(异常退出也是返回),再将这个帧从执行栈弹出。
每个帧主要包括两部分,一个局部变量表和一个操作数栈,关系如下图所示:
这里注意,局部变量表是根据索引访问的列表,类似数组;而操作数栈则是“后入先出”的栈,这里非常重要,因为java函数的字节码指令基本上都是对这两个数据结构进行操作。
局部变量表和操作数栈的大小取决于方法代码,在编译时计算,并随字节码指令一起写入class文件中,
public intgogo() {Log.i("zkw", "hello");return 888;
}
这是一个java方法,编译成class之后内容如下:
//access flags 0x1
publicgogo()I
LDC"zkw"LDC"hello"INVOKESTATIC android/util/Log.i (Ljava/lang/String;Ljava/lang/String;)I
POP
SIPUSH888IRETURN
MAXSTACK= 2MAXLOCALS= 1
最下面两行的MAXSTACK和MAXLOCALS的值就是操作数栈和局部变量表的大小。
局部变量表和操作数栈中的每个槽(slot)可以保存除long和double之外的任意java值,而long和double需要两个槽,比如向局部变量表储存一个int和一个long,则表中第一个位置是int值,第二和第三个位置存的是long值。
还有一点需要注意,如果是非静