毕业工作以来转到了.Net阵营对java有些生疏了,之前使用.Net的IL做了些aop相关的东西,终于有空学习学习与IL相似的ASM(刚刚接触,有错误忘大家指出,欢迎讨论)。
先谈谈个基本概念(建议看下这篇文章http://www.blogjava.net/libin2722/archive/2007/09/23/147513.html):
Bytecode (字节码)
C/C++编译器把源代码编译成汇编代码,Java编译器把Java源代码编译成字节码bytecode。
Java跨平台其实就是基于相同的bytecode规范做不同平台的虚拟机,我们的Java程序编译成bytecode后就可以在不同平台跑了。
.net框架有IL(intermediate language),汇编是C/C++程序的中间表达方式,而bytecode可以说是Java平台的中间语言。
来个简单的Demo,了解下ByteCode:
import java.io.PrintStream;
public class HelloWorld {
/**
* @param args
*/
public static void main(String[] args) {
// 下面两个控制台输出语句,结果是一样的
System.out.println("Hello world");// 直接调用System.out的静态方法println
PrintStream staticOutput = System.out;
staticOutput.println("Hello world");// 多做了一个store/load局部变量的操作,多引入了一个本地变量保存PrintStream(System.out)的地址
PrintStream output = new PrintStream(System.out);// 创建了一个PrintStream对象,使用了New指令在heap上分配了对象空间,并且使用一个局部变量用于保存PrintStream对象的堆指针(栈空间)
output.println("Hello world");
}
}
HelloWorld.java编译后的bytecode:
// class version 50.0 (50)
// access flags 0x21
public class HelloWorld {
// compiled from: HelloWorld.java
// access flags 0x1
public <init>()V//创建默认构造函数
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V//继承Object的构造函数
RETURN
L1
LOCALVARIABLE this LHelloWorld; L0 L1 0//所使用到的局部变量
MAXSTACK = 1//函数所使用到的栈最大的size
MAXLOCALS = 1//存放局部变量的最大size
// access flags 0x9
public static main([Ljava/lang/String;)V
L0//标记Label,跳转语句等跳转指向至Label
LINENUMBER 9 L0//行号标记,异常时候的堆栈信息就会用到这个
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello world"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L1
LINENUMBER 10 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ASTORE 1
L2
LINENUMBER 11 L2
ALOAD 1
LDC "Hello world"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L3
LINENUMBER 12 L3
NEW java/io/PrintStream//创建对象,分配堆空间
DUP//复制之前分配的PrintStream的引用并压入栈顶
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;//将今年静态对象System.out压栈
INVOKESPECIAL java/io/PrintStream.<init>(Ljava/io/OutputStream;)V//调用PrintStream(PrintStream ps)构造函数
ASTORE 2
L4
LINENUMBER 13 L4
ALOAD 2
LDC "Hello world"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L5
LINENUMBER 14 L5
RETURN
L6
LOCALVARIABLE args [Ljava/lang/String; L0 L6 0
LOCALVARIABLE staticOutput Ljava/io/PrintStream; L2 L6 1
LOCALVARIABLE output Ljava/io/PrintStream; L4 L6 2
MAXSTACK = 3
MAXLOCALS = 3
}
对应的Stack上的过程:

太晚了,这篇文章就简单介绍下bytecode,明天还要上班碎觉了,周末继续学习ASM。
欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
本文介绍了Java字节码(Bytecode)的基本概念及其与.NET IL的对比,并通过一个简单的HelloWorld示例展示了字节码的工作原理。同时,文章提到了即将开始学习与IL类似的Java字节码操作框架ASM。
1702

被折叠的 条评论
为什么被折叠?



