參考
字節碼指令 : http://gityuan.com/2015/10/24/jvm-bytecode-grammar/
從字節碼角度分析 i++ 和 ++i 實現 : http://www.lxweimin.com/p/7988e646a37e
java代碼:
public class ByteCodeDemo {
public static void main(String[] args) {
int i = 1;
int j = 5;
int dj = ++j;
int di = i++;
System.out.println(di);
System.out.println(dj);
}
}
class反編譯后:
Compiled from "ByteCodeDemo.java"
public class com.mpt.pomdemo.test.ByteCodeDemo {
public com.mpt.pomdemo.test.ByteCodeDemo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_5
3: istore_2
4: iinc 2, 1
7: iload_2
8: istore_3
9: iload_1
10: iinc 1, 1
13: istore 4
15: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
18: iload 4
20: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
23: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
26: iload_3
27: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
30: return
}
- load 命令:用于將局部變量表的指定位置的相應類型變量加載到棧頂;
- store命令:用于將棧頂的相應類型數據保入局部變量表的指定位置;
iconst_1 int型常量1進棧
istore_1 棧頂int數值存入變量表中的第2個位置
iconst_5 int型常量5進棧
istore_2 棧頂int數值存入變量表中的第3個位置
iinc 2, 1 將變量表中第3個位置加一
iload_2 將變量2進棧(下方 i++ 操作沒有這一步,所以i++還是沒執行加一操作的值)
istore_3 棧頂int數值存入第4局部變量
iload_1 將變量1進棧
iinc 1, 1 將變量表中第二個位置加一
istore 棧頂int數值存入第1局部變量
...
通過這個簡單的例子學習java class文件反編譯之后的命令在棧幀中的局部變量表和操作數棧中所作的操作,還有要注意指令的標號,并不是連續的,也就是有些操作并沒有展現出來
java的跨平臺特性:
javac命令:把.java文件編譯為class文件
java命令:jvm把class文件根據當前的操作系統 執行對應的操作
即編譯后的class文件無需修改即可實現跨平臺的特性
為什么JVM不直接把源碼解析成機器碼去執行?
1 準備工作:每次執行都需要各種檢查
2 兼容性 : 也可以將別的語言解析成字節碼