在Java中下面的两个程序的运行后i的值是不一样的,这一点和C或者C++有所不同,关键在于Java虚拟机的实现及其指令的特点。
(Java语言规范中的Java虚拟机规范)
- public class Inc{
- public static void main(String argv[]){
- int i=0;
- i=i++;
- }
- }
- 运行之后i=0。奇怪?为什么呢?
复制代码
对程序进行反汇编(注意不是反编译,如果是反编译得到的是Java代码不是Java汇编代码)
- $0 iconst_0 //push 'int' constant 0
- $1 istore_1 //store 'int' into local variable #1
- $2 iload_1 //load 'int' from local variable #1
- $3 iinc *1 1 //increment local variable by constant
- $6 istore_1 //store 'int' into local variable #1
- $7 return //return 'void' from method
复制代码
下面解释其中的Java汇编指令的含义:
(1)$0 iconst_0
iconst_<i> 作用是将常数i压入操作数栈,这里是0
(2)$1 istore_1
istore_<n> n是指当前局部变量帧中局部变量的索引,这里的1说明是第一个变量(我们的程序中只有一个变量,当然是第一个),指令从操作数栈顶弹出一个整型数放到指定的变量中,因此局部变量i的值被赋值为0。由此看到,这个和我们在8086汇编语言中看到的很不一样,在80x86中用MOV指令就可以了
(3)$2 iload_1
iload_<n> n是指当前局部变量帧中局部变量的索引,这里的1说明是第一个变量;指令把从变量取出的值压入操作数栈
(4)$3 iinc *1 1
iinc index const 该指令中index是指当前局部变量帧中局部变量的索引,const是说明在这个变量上加多少,在这条指令中将i加1。这条指令不影响操作数栈。
(5)$6 istore_1
关键在于这儿,该指令又从操作数栈顶弹出一个整型数放到指定的变量中;刚才第三条指令已经将0压入堆栈,所以弹出后赋值给i,结果i的值还是保持0不变。
(6)$7 return
方法返回,这个就不多说了
- public class Inc{
- public static void main(String argv[]){
- int i=0;
- i=++i;
- }
- }
- 运行之后i=1
复制代码
程序反汇编的结果
(1)$0 iconst_0 //push 'int' constant 0
//将0压入操作数栈
(2)$1 istore_1 //store 'int' into local variable #1
//从操作数栈顶弹出0存放在第一个变量i中
(3)$2 iinc *1 1 //increment local variable by constant
//i的值加1,所以i=1
(4)$5 iload_1 //load 'int' from local variable #1
//将第一个变量i的值压入操作数栈
(5)$6 istore_1 //store 'int' into local variable #1
//从操作数栈顶弹出值到i,所以i=1
(6)$7 return //return 'void' from method
//返回 |