ASM 学习笔记(一)

        毕业工作以来转到了.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上的过程:

ASM 学习笔记(一)_第1张图片
太晚了,这篇文章就简单介绍下bytecode,明天还要上班碎觉了,周末继续学习ASM。

 

欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

你可能感兴趣的:(学习笔记)