jvm自增,自减运行原理

简介: 在jvm中,涉及到变量运算时,会发生压栈弹栈等动作,但如果仅仅是自增和自减,那么jvm会直接在本地变量中实现。public class JavaTest{ public static void main(String[] args){ int ...

在jvm中,涉及到变量运算时,会发生压栈弹栈等动作,但如果仅仅是自增和自减,那么jvm会直接在本地变量中实现。

public class JavaTest{

    public static void main(String[] args){
        int a=1,b=1,c=1,d=1;
        a++;
        ++b;
        c = c++;
        d=++d;
        System.out.println(a+"..."+b+"..."+c+"..."+d);
    }
}

这段代码很简单,运行结果为2,2,1,2。
对于这样的结果大家可能都觉得是对的,因为c=c++的时候会先执行赋值操作,再进行自增,所以c等于1。但是c进行赋值之后,自增的操作也是c本身,为什么c这个变量不等于自增后的数值呢?
我们使用javap来将这段代码进行解析,结果如下:

F:\>javap -c JavaTest
Compiled from "JavaTest.java"
public class JavaTest {
  public JavaTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_1
       3: istore_2
       4: iconst_1
       5: istore_3
       6: iconst_1
       7: istore        4
       9: iinc          1, 1
      12: iinc          2, 1
      15: iload_3
      16: iinc          3, 1
      19: istore_3
      20: iinc          4, 1
      23: iload         4
      25: istore        4
      27: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      30: new           #3                  // class java/lang/StringBuilder
      33: dup
      34: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      37: iload_1
      38: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      41: ldc           #6                  // String ...
      43: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      46: iload_2
      47: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      50: ldc           #6                  // String ...
      52: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      55: iload_3
      56: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      59: ldc           #6                  // String ...
      61: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      64: iload         4
      66: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      69: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      72: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      75: return
}

下面我们来分析一下,前面0-7可以看出是定义了4个变量,分别进行压栈和弹栈操作,将变量最终放入到本地变量中。9这个操作就对应于代码中的a++,可以看出没有进行压栈和弹栈,只是执行了iinc,也就是自增操作,所以这个时候,本地变量中a就等于2。12对应于代码中的++b,情况和9类似。c=c++对应于15-19,从这里可以看出,jvm先执行了压栈,将c压入栈顶,然后执行自增操作,所以这个时候,栈顶的c为1,本地变量c为2,但是在这个时候,19又将栈顶的c弹栈并赋值给本地变量c了,所以本地变量c最终为1。d=++d和上面原理是一致的。
通过对代码的汇编码的分析,我们可以知道c=c++为什么等于自增前的c了,其实不是因为先进行了赋值,自增后的数据没有再次赋值,而是由于自增后被原数据给覆盖了。

目录
相关文章
|
2月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
2月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
68 3
|
2月前
|
前端开发 Java 应用服务中间件
JVM进阶调优系列(1)类加载器原理一文讲透
本文详细介绍了JVM类加载机制。首先解释了类加载器的概念及其工作原理,接着阐述了四种类型的类加载器:启动类加载器、扩展类加载器、应用类加载器及用户自定义类加载器。文中重点讲解了双亲委派机制,包括其优点和缺点,并探讨了打破这一机制的方法。最后,通过Tomcat的实际应用示例,展示了如何通过自定义类加载器打破双亲委派机制,实现应用间的隔离。
|
4月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
5月前
|
Java 编译器 程序员
JVM常见面试题(一):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别
JVM常见面试题(一):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别
JVM常见面试题(一):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别
|
4月前
|
消息中间件 设计模式 安全
多线程魔法:揭秘一个JVM中如何同时运行多个消费者
【8月更文挑战第22天】在Java虚拟机(JVM)中探索多消费者模式,此模式解耦生产与消费过程,提升系统性能。通过`ExecutorService`和`BlockingQueue`构建含2个生产者及4个消费者的系统,实现实时消息处理。多消费者模式虽增强处理能力,但也引入线程安全与资源竞争等挑战,需谨慎设计以确保高效稳定运行。
99 2
|
5月前
|
Java 程序员 C++
大牛程序员用Java手写JVM:刚好够运行 HelloWorld
大牛程序员用Java手写JVM:刚好够运行 HelloWorld
|
5月前
|
存储 算法 Java
(四)JVM成神路之深入理解虚拟机运行时数据区与内存溢出、内存泄露剖析
前面的文章中重点是对于JVM的子系统进行分析,在之前已经详细的阐述了虚拟机的类加载子系统以及执行引擎子系统,而本篇则准备对于JVM运行时的内存区域以及JVM运行时的内存溢出与内存泄露问题进行全面剖析。
115 0
|
5月前
|
JavaScript Java API
JAVA程序运行问题之JVM找到并开始执行main方法如何解决
JAVA程序运行问题之JVM找到并开始执行main方法如何解决
|
5月前
|
存储 Java
JAVA程序运行问题之JVM 中的栈如何解决
JAVA程序运行问题之JVM 中的栈如何解决