JVM字节码层面分析Java中的i++、++i

  Java语言在JVM虚拟机上运行,不可避免的涉及到JVM指令集,下面我们简单分析几个案例。

  在进行分析之前,先简单回顾一下JVM的运行时数据区中的JVM虚拟机栈。

一、JVM Stack - JVM虚拟机栈

  JVM Stack描述的是:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

  默认情况下,一个线程对应一个栈,一个方法对应一个栈帧。

  

二、示例代码分析

Demo1:

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

  输出结果是0。

Demo2:

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

   输出结果是1。

  对于初学者,往往会搞不明白为什么会出现这样的结果,下面我们通过JVM指令来分析这两个Demo。

1、Demo1的分析

  1.1、Demo1的mian()方法的局部变量表

  

    main() 方法的局部变量表中有两个变量,分别是序号为0的args、序号为1的 i。

  1.2、Demo1的main()方法的字节码指令 

  

   0、iconst_0 :将常量0压入操作数栈,

  

 

  1、istore_1 :   弹出操作数栈栈顶元素即常量0,存储到到局部变量表序号为1的位置即变量i中;

  至此 int i = 0 操作完成。

    

  2、iload_1: 第1个变量(变量值为0)压入操作数栈

 

  3、iinc 1 by 1:是将局部变量1中的数自增1

  

 4、istrore_1 : 弹出操作数栈栈顶元素即常量0,存储到到局部变量表序号为1的位置即变量i中;

   

 5、getstatic #2 : 获取常量池中#2对应变量的引用<java/lang/System.out : Ljava/io/PrintStream;> )压入操作数栈

 

 6、iload_1:第1个变量(变量值为0)压入操作数栈栈顶

   

 7、invokevirtual #3 调用常量池中#3对应的常量,即打印的方法( <java/io/PrintStream.println : (I)V>

   · 找到常量池 #3 项;

   · 定位到方法区 java/io/PrintStream.println:(I)V 方法

   · 生成新的printf() 栈帧(分配 locals、stack等)

    ·  传递参数i,执行新栈帧中的字节码

   · 执行完毕,弹出栈帧

  

 8、return 方法结束

  mian()  栈帧出栈

2、Demo2的分析

 2.1、Demo2的mian()方法的局部变量表与Demo1一致

 2.2、Demo1的main()方法的字节码指令

 

 0、iconst_0 :将常量0压入操作数栈

  

 1、istore_1 :   弹出操作数栈栈顶元素即常量0,存储到到局部变量表序号为1的位置即变量i中;至此 int i = 0 操作完成

  

 2、iinc 1 by 1:是将局部变量 i 中的数自增 1, 此时变量i = 1 

  

 3、iload_1: 第1个变量 i (变量值为1)压入操作数栈

  

 4、istore_1 :   弹出操作数栈栈顶元素 1,存储到到局部变量表序号为1的位置即变量 i 中

 

 5、getstatic #2 : 获取常量池中#2 对应变量的引用(<java/lang/System.out : Ljava/io/PrintStream;> )压入操作数栈

 6、iload_1 : 第1个变量(变量值为1)压入操作数栈栈顶

 7、invokevirtual   #3  :  调用常量池中#3对应的常量,即打印的方法( <java/io/PrintStream.println : (I)V>)

 8、return 方法结束

三、总结

  运行在JVM的业务逻辑,最终都是在JVM运行时数据区,通过JVM指令集,处理一系列变量值操作完成的。

posted @   无虑的小猪  阅读(390)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示

目录在这里