用java字节码解释i++和++i

用java字节码解释i++和++i - tutuhatec的专栏 - 博客频道 - CSDN.NET

先看4个题目:

①int i = 0;

i = i++;

②int i = 0;

i = ++i;

③int i = 0;

int j = 0;

j = i++ + i++;

④ int i = 0;

int j = 0;

j = i++ + i++ + i++;

每道题里的i和j都是多少?

用myeclipse测试,结果分别是①i = 0,②i = 1,③i = 2,j = 1,④i = 3,j = 3。

i++和++i的问题,困扰很多人。网上、书上的解释各种各样。现在通过分析字节码,来确定这两条语句究竟是怎样执行的。

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


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操作是有参数的,但是在此忽略,简写为iinc,此操作对应于自加操作,并且该操作不对stack有任何改变;

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

接下来是四段程序主要的字节码:

①iconst_0        ②iconst_0        ③iconst_0       ④iconst_0

istore_1            istore_1            istore_1           istore_1

iload_1             iinc 1,1              iconst_0          iconst_0

iinc 1,1             iload_1              istore_2           istore_2

istore_1            istore_1            iload_1             iload_1

iinc 1,1             iinc 1,1

iload_1             iload_1

iinc 1,1             iinc 1,1

iadd                  iadd

istore_2            iload_1

iinc 1,1

iadd

istore_2

现在解释①。第一步在stack中存入一个int常量0;第二步把它赋值给第一个变量,即我们的i;第三步把第一个变量i的值存入到stack中;第四步在i自身的空间进行自加,而第三步存入到stack中的值没有变;第五步把第三步存入到stack中的值再赋值给第一个变量i。也就是说,i真的是进行自加了,但是被自己原来的值覆盖掉了。从这里我们可以看出,自加操作比赋值操作的优先级高。

再看②。和①比较起来,区别就在于,++i是先进行自加,然后把自加后的值存入到stack中,所以最后赋值给i的是1,不是0。

③呢?首先,③比前两个多了一个变量,但这不是重点。往下看,把第一个变量i的值(0)存入到stack中,i自加,再第一个变量i的值(1)存入到stack中,再自加。此时stack中有两个值了,0和1,进行加操作后的结果是1,然后赋值给第二个变量j。这里颠覆了我们以前被告知的,加的运算优先级比自加高。这就是困扰我们的,其实,只要把值读入到stack中,接下来就进行自加,只有得到了两个参数,才进行加操作。

来看④。前面都和③一样,只到进行了第一次加操作,得到的结果(1)保存在stack中,没有赋值给j,然后再次读入i的值(2)到stack,i自加,得到加操作的两个参数,1和2,进行第二次加操作的结果是3,赋值给j。

到此,问题都解决了。

时间: 2024-11-10 07:11:22

用java字节码解释i++和++i的相关文章

用java字节码解释i++和++i(转)

先看4个题目: ①int i = 0; i = i++; ②int i = 0; i = ++i; ③int i = 0; int j = 0; j = i++ + i++; ④ int i = 0; int j = 0; j = i++ + i++ + i++; 每道题里的i和j都是多少? 结果分别是①i = 0,//出现0可以这样简单理解:自增是单独的一个操作,自增的结果不会体现在变量i上.i++,本身就是逻辑运算(i=i+1)的缩写.//容易混淆的地方就在于定义的变量i和自增操作的变量i名

关于java字节码框架ASM的学习

一.什么是ASM ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能.ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为.Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称.方法.属性以及 Java 字节码(指令).ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类.asm字节码增强技术主要是用来反射的时候提升性能的,

从Java源码到Java字节码

Java最主流的源码编译器,javac,基本上不对代码做优化,只会做少量由Java语言规范要求或推荐的优化:也不做任何混淆,包括名字混淆或控制流混淆这些都不做.这使得javac生成的代码能很好的维持与原本的源码/AST之间的对应关系.换句话说就是javac生成的代码容易反编译. Java Class文件含有丰富的符号信息.而且javac默认的编译参数会让编译器生成行号表,这些都有助于了解对应关系. 关于Java语法结构如何对应到Java字节码,在JVM规范里有相当好的例子:Chapter 3.

这一次,彻底弄懂「Java字节码文件」

提前祝福各位读者??圣诞快乐!这个圣诞节请在学习中度过! 不啰嗦,直接从最最简单的一段Java源代码开启Java整体字节码分析之旅. 1.Java 源码文件 package com.dskj.jvm.bytecode; public class MyTest1 { private int a = 1; public int getA() { return a; } public void setA(int a) { this.a = a; } } 2.Java字节码文件 IDEA工具编译代码后,

java字节码忍者禁术

Java语言本身是由Java语言规格说明(JLS)所定义的,而Java虚拟机的可执行字节码则是由一个完全独立的标准,即Java虚拟机规格说明(通常也被称为VMSpec)所定义的. JVM字节码是通过javac对Java源代码文件进行编译后生成的,生成的字节码与原本的Java语言存在着很大的不同.比方说,在Java语言中为人熟知的一些高级特性,在编译过程中会被移除,在字节码中完全不见踪影. 这方面最明显的一个例子莫过于Java中的各种循环关键字了(for.while等等),这些关键字在编译过程中会

通过Java字节码发现有趣的内幕之String篇(上)(转)

原文出处: jaffa 很多时候我们在编写Java代码时,判断和猜测代码问题时主要是通过运行结果来得到答案,本博文主要是想通过Java字节码的方式来进一步求证我们已知的东西.这里没有对Java字节码知识进行介绍,如果想了解更多的Java字节码或对其感兴趣的朋友可以先阅读字节码基础:JVM字节码初探. String字面量可以通过’==’判断两个字符串是否相同,是因为大家都知道’==’是用来判断两个对象的值引用地址是否一致,两个值一样的字符串字面量定义是否指向同一个值内存地址呢?答案是肯定的. 1

如何调教java字节码

本文地址:http://www.cnblogs.com/herbix/p/3541093.html java字节码是直接在在jvm上运行的代码.和简单易懂的java程序不同,java字节码是类似于汇编的指令串,不过比汇编的指令集要小很多,java字节码可优化的余地没有那么大,想直接编写字节码也要比编写汇编容易许多. <JAVA虚拟机规范 java SE 7>这本书上详细介绍了制作一个java虚拟机的过程,包括类文件的结构.指令集.还有一些约束等等,其余的部分是由虚拟机的编写者决定的.既然我们的

Java字节码 小结

Reference javap 基本使用方法 深入理解java字节码 从Java代码到字节码 Java字节码.class文件案例分析 字节码 核心概念 Class文件是8位字节流,按字节对齐.之所以称为字节码,是由于每条指令都仅仅占领一个字节.全部的操作码和操作数都是按字节对齐的. 数据结构 Java虚拟机规范中规定.Class文件格式採用一种相似C语言结构体的伪结构来存储,它仅仅有两种数据类型 无符号数(基本数据类型) 主要用于描写叙述数字.索引引用.数量值.或UTF-8编码构成的字符串: u

JAVA字节码修改异常分析

源class反编译后代码如下: public boolean isExpiring() { if ((this.timestamp == null) || (this.timestamp.length() <= 0)) { return true; } boolean isExpiring = false; try { SimpleDateFormat df = new SimpleDateFormat( SSOAuthConfig.getAuthDataDateFormart()); Date