为什么对象被new 以后在执行dup操作?
为什么对象被new 以后在执行dup操作?
今天有个朋友问我,为什么一个new一个对象的指令在new后面紧跟的是dup操作?他说搜了可能找到的
搜索引擎都找不到答案,包括翻了<<深入JAVA虚拟机指令>>这本书也没有任何说明.
我们先来看看为dup指令的作用,dup指令可以复制栈顶的一个字再压入栈,也就是把栈顶的内容做个备份.
大家知道,JAVA/CLR是完全基于栈的实现,任何操作都是入栈出栈,没有任何寄存器,所以如果要对某一操作
数做两次连续操作,那就要复制两次栈顶操作数,比如:
int x;
int y = x = 2;
当常数2被压入栈顶后,它要连续两次store到变量x和y,所以这里编译后肯定有一个dup操作:
bipush 20
dup
istore_1
istore_2
如果不做dup操作,那么istore_1将20存到内存中的x后,再istore_2要么没有操作数,要么是一个其它的操作数.
当然这在编译时对连续操作已经做dup操作了,所以不会真的出现这个情况.
那么new 指令后,为什么一定要dup操作呢?
因为java代码的new操作编译为虚拟机指令后,虚拟机指令new在堆上分配了内存并在栈顶压入了指向这段内存的
地址供任何下面的操作来调用,但是在这个操作数被程序员能访问的操作之前,虚拟机自己肯定要调用对象的
方法,也就是如果程序员做一个 Type a = new Type();其实要连续两次对栈顶的操作数进行操作.其中一
次是虚拟机内部自动调用的,这种情况是99%以上存在的,而java 编译器是一种聪明的编译器,所以只要有new操作
就优化为将对象的地址操作数DUP,第一次调用invokespecial 时会弹出一个,下面一个留给对该对象访问
的操作,即使你的代码是:new Type();没有任何引用.有些虚拟机也会先dup(不同版本编译结果不同),然后时弹出
一个操作数,后面会立即pop掉被复制的那个操作数.这样的做目的是为了编译优化.
有人说那可以直接从栈顶先store到内存中,需要操作的时候再load到栈顶啊,注意再没有操作这前对象对于
程序员是不可见的,否则就会访问到残废的对象,所以只能是先然后才能store到内存中.这两步操作的操作数必须都直接是原来已经存在栈中的,所以只能是dup.
转自 http://www.voidcn.com/article/p-bytplmaq-bkm.html
为什么对象被new 以后在执行dup操作?的更多相关文章
- handler.post 为什么要将thread对象post到handler中执行呢?
转载网址:http://www.cnblogs.com/crazypebble/archive/2011/03/23/1991829.html在Android中使用Handler和Thread线程执行 ...
- 【java】对象变成垃圾被垃圾回收器gc收回前执行的操作:Object类的protected void finalize() throws Throwable
package 对象被回收前执行的操作; class A{ @Override protected void finalize() throws Throwable { System.out.prin ...
- JS事件 光标聚焦事件(onfocus)当网页中的对象获得聚点时,执行onfocus调用的程序就会被执行
光标聚焦事件(onfocus) 当网页中的对象获得聚点时,执行onfocus调用的程序就会被执行. 如下代码, 当将光标移到文本框内时,即焦点在文本框内,触发onfocus 事件,并调用函数messa ...
- 转:handler.post 为什么要将thread对象post到handler中执行呢?
转载网址:http://blog.csdn.net/fei0724/article/details/8664462在Android中使用Handler和Thread线程执行后台操作 对于线程的控制,我 ...
- 使用 JavaScript 中的 window 对象执行计时操作,完成一个抽奖程序
查看本章节 查看作业目录 需求说明: 使用 JavaScript 中的 window 对象执行计时操作,完成一个抽奖程序 实现思路: 在 HTML 页面中放置背景图片.转盘和指针 3 张图片,并设置指 ...
- 判断数组对象里面的某个属性全部为true才执行下一步操作
比如数据[ {name:'张三',isshow:'false'},name:'李四',isshow:'false'}, ] 这里是自己写的验证,没用elemten的 如果有2张票,需要刷2张身份证,则 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (27) ------ 第五章 加载实体和导航属性之关联实体过滤、排序、执行聚合操作
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-9 关联实体过滤和排序 问题 你有一实体的实例,你想加载应用了过滤和排序的相关 ...
- 使用MyBatis对表执行CRUD操作
一.使用MyBatis对表执行CRUD操作——基于XML的实现 1.定义sql映射xml文件 userMapper.xml文件的内容如下: <?xml version="1.0&quo ...
- MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作(转载)
本文转载自:http://www.cnblogs.com/jpf-java/p/6013540.html 上一篇博文MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybati ...
随机推荐
- Map:template
ylbtech-Map-Amap|Baidu: 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 9. ...
- NTP时钟调整策略
一. 问题背景 天威视讯项目3月底发生了一次点播出现节目请求超时的情况,在查询故障的过程中,发现MAP服务器操作系统的时钟被向前调整了11秒,姑且不论是否是这个原因导致的故障,但每台服务 ...
- 测开之路四十:jQuery基本用法
从cdn引入jQuery库:https://www.bootcdn.cn/,搜索jQuery 在html里面(使用之前计算器的脚本),把复制的标签粘贴到引入js标签的前面:<script src ...
- mac 上查看python3的各种安装路径
1.mac chromedriver的安装目录:/usr/local/bin 2.mac htmltestrunner的存放目录:命令行下 import sys sys.path/Library/Fr ...
- 获取header中content-type的值
后台传过来的值需要根据content-Type的值来判定成功与否 获取header中content-Tyep的值 用res.header['Content-Type']
- git使用记录二: 给文件重命名的简单方法
git使用记录三: 给文件重命名的简单方法 git mv file_name_old file_name_new mv: 文件命名 file_name_old : 文件当前的名字 file_name_ ...
- 【python】 字符串转小写(含汉字等时仍work)
def mylower(str): outstr = ""; strlen = len(str); idx = 0; while idx < strlen: if ord(s ...
- static关键字_1
static关键字 1.在类中,用static声明的成员变量为静态成员变量,它为该类的公用变量,在第一次使用时被初始化,对于该类的所以对象来说,static成员变量只有一份. 2.用static声 ...
- MySQL数据库时区问题导致java程序无法连接数据库
转载自https://blog.csdn.net/man_zuo/article/details/81027934 先把报错信息贴上, The server time zone value '???ú ...
- MySQL-mysql_config_editor安全登录工具
mysql_config_editor出现在mysql5.6.6以后的版本,可以给指定的连接和密码生成一个加密文件.mylogin.cnf,默认位于当前用户家目录下.通过该文件可以使用mysql.my ...