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

 

i ++

++ i

i
-=- 1

i
+= 1

 

以上的四句代码,问那句的执行速度更快?

对于C/C++程序员来说,可能首先想到的就是i++和++i要比其他两者要快一些,但是在Java中是不是这样的呢?

我们可以对他进行一些分析,首先当然想到的是对这些语句利用Java的System.currentTimeMillis()计算单个语句运行很多次(如10亿次)后的时间,然后作比较.

例如这样:

测试环境:(1)Windows XP sp3 (2)JDK "1.6.0_07"   Client VM (build 10.0-b23, mixed mode, sharing)

 

ContractedBlock.gif ExpandedBlockStart.gif 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));

    }
}

 

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

increment

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

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

JVM

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

ContractedBlock.gif ExpandedBlockStart.gif Code
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类型值。

转载于:https://www.cnblogs.com/ChrisWang/archive/2009/09/21/1571812.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值