用字节码解释i++,++i

首先看代码

public static void main(String[] args) {
        int i = 0;
        i = i++;
        System.out.println(i);
    }

打印结果是0,而如果是i=++i,那么打印将会1。下面我们从字节码的角度来分析为什么是这样。

在讲字节码之前,先简单的了解下Java栈,在JVM中有这么一个数据结构叫Java栈,当线程启动的时候,会分配一块内存当做该线程的栈,每个栈由一系列的栈帧组成。每个栈帧对应一个方法,当线程执行方法时,就是栈帧出栈入栈的过程。

每个栈帧包含三部分数据:本地变量(参数+方法内的变量)、操作数栈和其它数据,本文主要涉及本地变量和操作数栈。

先看后置i++的实现

public static void main(String[] args) {
        int i = 0;
        i = i++;
    }

编译之后的字节码如下:

整个过程这样的:

 可以发现变量在执行命令iinc 1,1的时候已经变成1了,但是istore_1又把变量所在位置覆盖成了0,所以执行完i = i++,i还是原来那个值。

下面,来看下前置++的实现:

字节码就不再解释了,整个过程实现如下:

和后置++不同的地方在于,在变量进入操作数栈之前,就先执行了iinc指令,所以进入操作数的值是加1后的值,最后写回的值也是最新值。

 

给出今天用到的字节码的含义

Bytecode

Stack

before->after

Description

iconst_0

->0

Loads the int value 0 onto the stack

istore_1

value->

Store int value into variable 1

istore_2

value->

Store int value into variable 2

iinc

No change

Increment local variable #index by signed byte const

iload_1

->value

Loads an int value from variable 1

iadd

value 1,value 2->result

Adds 2 ints together

 

 

 

 

 

 

 

 

 

 

 

 

 

 

说明两点需要注意的地方:

①iinc此操作对应于自加操作,并且该操作不对stack有任何改变;

②iadd操作过后只在stack中保留结果result。

 

原文链接:https://mp.weixin.qq.com/s/Vmf5uPmZrloPkbASSy3M8w

 

 

posted @ 2018-04-30 18:35  清晨_  阅读(345)  评论(0编辑  收藏  举报