参考
字节码指令 : http://gityuan.com/2015/10/24/jvm-bytecode-grammar/
从字节码角度分析 i++ 和 ++i 实现 : https://www.jianshu.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 兼容性 : 也可以将别的语言解析成字节码