Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂

简介: Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂

一、Java的i = i++深入JVM指令讲解 图文并茂 看了必懂

先看一段简单的代码

package com.zhou.jvm.runtimedataAreainstructionset;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/5-19:55
 */
public class TestPlusPlus {
    public static void main(String[] args) {
        int i = 8;
        i = i++;
        System.out.println(i);
    }
}

最后程序打印的结果是8不是9

那么这个是为什么呢?我们从JVM指令来看

编译这个类之后我们用jclasslib插件show bytecode with jclasslib,可以看到如下

我把里面的Bytecode单独拿出来,粘在这里

0 bipush 8
 2 istore_1
 3 iload_1
 4 iinc 1 by 1
 7 istore_1
 8 getstatic #2 <java/lang/System.out>
11 iload_1
12 invokevirtual #3 <java/io/PrintStream.println>
15 return

接下来一条一条指令的解析

1. bipush 8

第一步,bipush指令具体的含义就是把一个int类型的数据压入操作数栈。具体的可以参照官网链接,如下图所示把8压入了操作数栈

2. istore_1

第二步,istore_1就是将操作数栈的数字弹出栈并写入局部变量表当中建立的一个index值为1的索引的变量,这里程序的i变量此时就为8,完成了int i = 8的操作。

3. iload_1

第三步,iload_1指令就是将局部变量表中的值再次压入操作数栈当中去。所以此时操作数栈里面的值此时为8

4. iinc 1 by 1

第四步,iinc 1 by 1就是将局部变量表中索引值为1的变量加一,就是完成了i++这一步操作,此时局部变量表中的i为9

5. istore_1

第五步,istore_1就是将操作数栈的数字弹出栈并写入局部变量表当中建立的一个index值为1的索引的变量,这里程序的i变量此时就为8,完成了int i = i++的操作。

6. iload_1

因此最后输出的就是8

二、换成i=++i的JVM指令研究

package com.zhou.jvm.runtimedataAreainstructionset;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/5-19:55
 */
public class TestPlusPlus {
    public static void main(String[] args) {
        int i = 8;
        i = ++i;
        System.out.println(i);
    }
}

这个类的Bytecode

i=++i的bytecode

0 bipush 8
 2 istore_1
 3 iinc 1 by 1
 6 iload_1
 7 istore_1
 8 getstatic #2 <java/lang/System.out>
11 iload_1
12 invokevirtual #3 <java/io/PrintStream.println>
15 return

把i = i++的bytecode拿出来对比

0 bipush 8
 2 istore_1
 3 iload_1
 4 iinc 1 by 1
 7 istore_1
 8 getstatic #2 <java/lang/System.out>
11 iload_1
12 invokevirtual #3 <java/io/PrintStream.println>
15 return

可以看出两者之间的区别在于 iload_1 和 iinc 1 by 1的顺序问题

i=++i的是先 iinc 1 by 1再 iload_1,就是说先对局部变量表的变量进行自增再把这个自增以后的值压入操作数栈,自然这个操作数栈的数据已经+1了

i=i++的是先iload_1 再iinc 1 by 1,就是说先把局部变量表中的变量的值压入操作数栈,再进行自增操作,所以这个对于后续的istore_1操作有影响,使得这个最终的局部变量表中的数据还是之前没有加1的那个数值。


相关文章
|
26天前
|
监控 算法 Java
Java虚拟机(JVM)的垃圾回收机制深度解析####
本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
|
18天前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
25 0
|
15天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
17天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
21天前
|
机器学习/深度学习 监控 算法
Java虚拟机(JVM)的垃圾回收机制深度剖析####
本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
31 1
|
21天前
|
Oracle 安全 Java
深入理解Java生态:JDK与JVM的区分与协作
Java作为一种广泛使用的编程语言,其生态中有两个核心组件:JDK(Java Development Kit)和JVM(Java Virtual Machine)。本文将深入探讨这两个组件的区别、联系以及它们在Java开发和运行中的作用。
48 1
|
1月前
|
监控 Java 开发者
Java虚拟机(JVM)深度优化指南####
本文深入探讨了Java虚拟机(JVM)的工作原理及其性能优化策略,旨在帮助开发者通过理解JVM的内部机制来提升Java应用的运行效率。不同于传统的技术教程,本文采用案例分析与实战技巧相结合的方式,为读者揭示JVM调优的艺术。 ####
58 8
|
27天前
|
监控 算法 Java
深入理解Java虚拟机(JVM)的垃圾回收机制
【10月更文挑战第21天】 本文将带你深入了解Java虚拟机(JVM)的垃圾回收机制,包括它的工作原理、常见的垃圾收集算法以及如何优化JVM垃圾回收性能。通过本文,你将对JVM垃圾回收有一个全新的认识,并学会如何在实际开发中进行有效的调优。
41 0
|
2月前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
2月前
|
存储 算法 Java
深入理解Java虚拟机(JVM)及其优化策略
【10月更文挑战第10天】深入理解Java虚拟机(JVM)及其优化策略
49 1