您的位置:首页 > 编程语言 > Java开发

Java之深入JVM(1) - 由i++ 和 ++i的执行速度所想到的

2013-06-11 20:53 323 查看
Code
public class Increment {

public int preIncrement() {
int i = 0;

++i;

return i;
}

public int postIncrement() {

int i = 0;
i++;

return
i;
}

public int negative() {
int i = 0;
i
-= -1;

return
i;
}

public int plusEquals() {
int i = 0;

i
+= 1;
return i;
}

public static void main(String[] args) {
Increment in
= new Increment();
long start
=
System.currentTimeMillis();
for (int i = 0; i < 1000000000;
i++) {

in.preIncrement();
}

System.out.println("preIncrement:"

+
(System.currentTimeMillis() - start));

start =
System.currentTimeMillis();
for (int i = 0; i < 1000000000;
i++) {

in.postIncrement();
}

System.out.println("postIncrement:"

+
(System.currentTimeMillis() - start));

start =
System.currentTimeMillis();
for (int i = 0; i < 1000000000;
i++) {

in.negative();
}

System.out.println("negative:" +
(System.currentTimeMillis() - start));

start =
System.currentTimeMillis();
for (int i = 0; i < 1000000000;
i++) {

in.plusEquals();
}

System.out

.println("plusEquals:" +
(System.currentTimeMillis() - start));

}
}

运行结果,发现四次结果都不一样但是差别极其微小,如图:





但是这样我们是不是就可以说,这四个语句的运行在Java中是有差别或者是无差别的呢?当然不能这样去说,这个程序的具体运行还受限于当前机器的所运行的其他程序以及JVM中的JIT引擎对执行代码的优化等。

其实一个比较合理的办法利用Javap反汇编这个文件,去看看反汇编后各个方法所生成的字节码,由于JVM在运行的时候就是执行这些中间代码,所以比较能够说明问题.





然后我运行javap –c –v
com.jni.test.tracker.object.Increment去反汇编这个代码,得到了preIncrement,postIncrement,negative,plusEquals方法各自的字节码如下:

public int preIncrement();
Code:
Stack=1, Locals=2, Args_size=1
0:   iconst_0
1:   istore_1
2:   iinc    1, 1
5:   iload_1
6:   ireturn
LineNumberTable:
line 5: 0
line 6: 2
line 7: 5

LocalVariableTable:
Start  Length  Slot  Name   Signature
0      7      0    this       Lcom/jni/test/tracker/object/Increment;
2      5      1    i       I

public int postIncrement();
Code:
Stack=1, Locals=2, Args_size=1
0:   iconst_0
1:   istore_1
2:   iinc    1, 1
5:   iload_1
6:   ireturn
LineNumberTable:
line 11: 0
line 12: 2
line 13: 5

LocalVariableTable:
Start  Length  Slot  Name   Signature
0      7      0    this       Lcom/jni/test/tracker/object/Increment;
2      5      1    i       I

public int negative();
Code:
Stack=1, Locals=2, Args_size=1
0:   iconst_0
1:   istore_1
2:   iinc    1, 1
5:   iload_1
6:   ireturn
LineNumberTable:
line 17: 0
line 18: 2
line 19: 5

LocalVariableTable:
Start  Length  Slot  Name   Signature
0      7      0    this       Lcom/jni/test/tracker/object/Increment;
2      5      1    i       I

public int plusEquals();
Code:
Stack=1, Locals=2, Args_size=1
0:   iconst_0
1:   istore_1
2:   iinc    1, 1
5:   iload_1
6:   ireturn
LineNumberTable:
line 23: 0
line 25: 2
line 26: 5

LocalVariableTable:
Start  Length  Slot  Name   Signature
0      7      0    this       Lcom/jni/test/tracker/object/Increment;
2      5      1    i       I


令人惊讶的是,虽然这四个方法是不一样的,但是经过Java编译器优化后,我们发现生成的四个方法的bytecode实际都是一样的。

下面简单讲解一下这几句bytecode

iconst_0:将int类型的值0压入栈

istore_1: 从栈中弹出int类型值,然后将其存到位置为0的局部变量中

iinc 1,1 : 为局部变量中位置为1的int数 加1

iload_1 : 将局部变量中位置为1的int变量入栈

ireturn : 从栈中弹出int类型值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: