(转)java反编译i++和++i问题
转自:http://blog.csdn.net/junsure2012/article/details/7099222
java字节码指令集:http://www.jb51.net/article/36407.htm
java执行代码分析:http://www.kuqin.com/java/20111031/314144.html
1.javap是什么:
where options include:
-c Disassemble the code
-classpath <pathlist> Specify where to find user class files
-extdirs <dirs> Override location of installed extensions
-help Print this usage message
-J<flag> Pass <flag> directly to the runtime system
-l Print line number and local variable tables
-public Show only public classes and members
-protected Show protected/public classes and members
-package Show package/protected/public classes
and members (default)
-private Show all classes and members
-s Print internal type signatures
-bootclasspath <pathlist> Override location of class files loaded
by the bootstrap class loader
-verbose Print stack size, number of locals and args for met
hods
If verifying, print reasons for failure
以上为百度百科里对它的描述,只是介绍了javap的一些参数和使用方法,而我们要用的就是这一个:-c Disassemble the code。
明确一个问题:javap是什么?网上有人称之为 反汇编器,可以查看java编译器为我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。
2.初步认识javap
从一个最简单的例子开始:

这个例子中,我们只是简单的声明了两个int型变量并赋上初值。下面我们看看javap给我们带来了什么:(当然执行javap命令前,你得首先配置好自己的环境,能用javac编译通过了,即:javac TestJavap.java )

我们只看(方便起见,将注释写到每句后面)
Code:
0: iconst_2 //把2放到栈顶
1: istore_1 //把栈顶的值放到局部变量1中,即i中
2: iconst_3 //把3放到栈顶
3: istore_2 //把栈顶的值放到局部变量1中,即j中
4: return
是不是很简单?(当然,估计需要点数据结构的知识) ,那我们就补点java的关于堆栈的知识:
对于 int i = 2;首先它会在栈中创建一个变量为i的引用,然后查找有没有字面值为2的地址,没找到,就开辟一个存放2这个字面值的地址,然后将i指向2的地址。
看了这段话,再比较下上面的注释,是不是完全吻合?
为了验证上面这一说法,我们继续实验:

我们将 i 和 j的值都设为2。按照以上理论,在声明j的时候,会去栈中招有没有字面值为2的地址,由于在栈中已经有2这个字面值,便将j直接指向2的地址。这样,就出现了i与j同时均指向2的情况。
拿出javap -c进行反编译:结果如下:

Code:
0: iconst_2 //把2放到栈顶
1: istore_1 //把栈顶的值放到局部变量1中,即i中
2: iconst_2 //把2放到栈顶
3: istore_2 //把栈顶的值放到局部变量2中,即j中(i 和 j同时指向2)
4: return
虽然这里说i和j同时指向2,但这里不等于说i和j指向同一块地址(java是不允许程序员直接修改堆栈中的数据的,所以就不要想着,我是不是可以修改栈中的2,那样岂不是i和j的值都会变化。另:在编译器内部,遇到j=2;时,它就会重新搜索栈中是否有2的字面值,如果没有,重新开辟地址存放2的值;如果已经有了,则直接将j指向这个地址。因此,就算j另被赋值为其他值,如j=4,j值的改变不会影响到i的值。)
再来一个例子:

还是javap -c

Code:
0: iconst_2 //把2放到栈顶
1: istore_1 //把栈顶的值放到局部变量1中,即i中
2: iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是2
3: istore_2 //把栈顶的值放到局部变量2中,即j中
4: return
看到这里是不是有点明确了?
既然我们对javap有了一定的了解,那我们就开始用它来解决一些实际的问题:
1.i++和++i的问题

反编译结果为

Code:
0: iconst_1
1: istore_1
2: iinc 1, 1 //这个个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,i此时变成2了
5: iconst_1
6: istore_2
7: iinc 2, 1//这个个指令,把局部变量2,也就是j,增加1,这个指令不会导致栈的变化,j此时变成2了
10: return
可以看出,++在前在后,在这段代码中,没有任何不同。
我们再看另一段代码:

反编译结果:

Code:
0: iconst_1
1: istore_1
2: iload_1
3: iinc 1, 1 //局部变量1(即i)加1变为2,注意这时栈中仍然是1,没有改变
6: istore_1 //把栈顶的值放到局部变量1中,即i这时候由2变成了1
7: iconst_1
8: istore_2
9: iinc 2, 1 //局部变量2(即j)加1变为2,注意这时栈中仍然是1,没有改变
12: iload_2 //把局部变量2(即j)的值放到栈顶,此时栈顶的值变为2
13: istore_2 //把栈顶的值放到局部变量2中,即j这时候真正由1变成了2
14: return
是否看明白了? 如果这个看明白了,那么下面的一个问题应该就是迎刃而解了:

m = m ++;这句话,java虚拟机执行时是这样的: m的值加了1,但这是栈中的值还是0, 马上栈中的值覆盖了m,即m变成0,因此不管循环多少次,m都等于0。
如果改为m = ++m; 程序运行结果就是100了。。。
转自:http://blog.csdn.net/luckyp/archive/2009/06/09/4255353.aspx
(转)java反编译i++和++i问题的更多相关文章
- [Java基础]代码块及java反编译
块的作用域: 块(即复合语句)是指一对花括号括起来的若干条简单的java语句.块确定了变量的作用域.一个块可以嵌套在另一个块中.但是,在嵌套的两个块中声明同名的变量时应注意,块中变量申明在块外变量 ...
- Java反编译插件JadClipse
Java反编译是很容易的,现在就介绍一个反编译插件,以后我们通过Ctrl+鼠标左键查看源码就容易得多了,不用再担心源码找不到了,配置过程很简单的. 准备: 1.下载JadClipse(jar文件,ec ...
- eclipse安装JAVA反编译插件
前言:在实际的开发中几乎都会使用到一些框架来辅助项目的开发工作,对于一些框架的代码我们总怀有一些好奇之心,想一探究竟,有源码当然更好了,对于有些JAR包中的代码我们就需要利用反编译工具来看一下了,下面 ...
- Java反编译利器-Jad, Jode, Java Decompiler等及其IDE插件
转自:http://blog.csdn.net/superbeck/article/details/5189231 对于长年使用Java的程序员,大部分应该都会或多或少的使用到反编译软件.毕竟,不可能 ...
- 【转】Eclipse Class Decompiler——Java反编译插件
闲暇之余,写了一个Eclipse下的Java反编译插件:Eclipse Class Decompiler,整合了目前最好的2个Java反编译工具Jad和JD-Core,并且和Eclipse Class ...
- java反编译工具JD-GUI
这款java反编译工具是由C++写的,是一款免费的非商业用途的软件,(Xjad也不错,但是不支持jar反编译) 一.支持众多.class反编译工具 二.支持反编译jar
- 7 款开源 Java 反编译工具
今天我们要来分享一些关于Java的反编译工具,反编译听起来是一个非常高上大的技术词汇,通俗的说,反编译是一个对目标可执行程序进行逆向分析,从而得到原始代码的过程.尤其是像.NET.Java这样的运行在 ...
- myeclipse和eclipse安装Java反编译插件
为myeclipse和eclipse安装Java反编译插件 插件所需包 1.解压jad1.5.8g.zip.将jad.exe放到jre的bin目录下,下载地址: http://ishare.ia ...
- java反编译工具
由于JAVA语言安全性高.代码优化.跨平台等特性,从1995年5月由SUN公司发布后,迅速取代了很多传统高级语言,占据了企业级网络应用开发等诸多领域的霸主地位. 不过,JAVA最突出的跨平台优势使得它 ...
- java反编译工具(XJad)
java反编译工具(XJad) 2.2 绿色版 http://www.cr173.com/soft/35032.html Demo.class ---> Demo.java
随机推荐
- ES6 async 与 await 实战
下面来说一说通过async和await方式来辅助请求和封装 首先我们定义一个类,定义一个async方法,才可以使用await class JForm extends React.Component { ...
- onWindowFocusChanged重要作用(得到/失去焦点call) 、
onWindowFocusChanged重要作用 Activity生命周期中,onStart, onResume, onCreate都不是真正visible的时间点,真正的visible时间点是onW ...
- JavaWeb 获取ip地址
JavaWeb 获取ip地址 CreateTime--2018年5月31日17点56分 Author:Marydon import java.net.InetAddress; import jav ...
- 05-spring-bean注入
spring中只有两大核心技术: 控制反转(IOC)&依赖注入(DI),AOP(面向切面编程) 依赖注入:指利用配置文件的关系,来决定类之间的引用关系,以及数据的设置操作. 构造方法注入 默认 ...
- oracle update left join查询
对于有的更新语句,要更新的表可能条件不够,需要用到left join关联其他表, 但是不能直接关联,否则报错:错误如下: update imim_gireqbillitems gi left join ...
- [Java Performance] JVM 线程调优
调整线程栈空间 当很缺少内存时,能够调整线程使用的内存. 每一个线程都有一个栈,用来记录该线程的调用栈信息.线程中的栈的默认空间是有OS和JVM的版本号决定的: OS 32-bit 64-bit Li ...
- Springmvc UPDATE 数据时 ORA-01858:a non-numeric character was found where a numeric was expected
ORA-01858:a non-numeric character was found where a numeric was expected 异常. 我的代码: 主要是绑定变量带出来的问题. 出错 ...
- 自定义基于XML的验证器
a.编写一个类,继承FieldValidatorSupport类. b.在public void validate(Object object)编写你的验证逻辑 不符合要求的就向fieldErrors ...
- unity, unity中GL.MultMatrix的一个超级bug
GL.MultMatrix与OpenGL固定管线的glMultMatrix函数行为并不一致,不是累乘,而是覆盖. 例如下面例子,本来预期是在(100,100)处画一个方块,而实际效果却是在(0,0)处 ...
- 自己定义进度条PictureProgressBar——从开发到开源公布全过程
自己定义进度条PictureProgressBar--从开发到开源公布全过程 出处: 炎之铠邮箱:yanzhikai_yjk@qq.com 本文原创.转载请注明本出处! 本项目JCenter地址:ht ...