java虚拟机指令dup详解
本文实例为大家介绍了java虚拟机指令dup,供大家参考,具体内容如下
举个例子:
public class ExceptionTest{ void cantBeZero(int i) throws Exception{ throw new Exception(); } }
上面代码编译后的字节码指令如下:
void cantBeZero(int) throws java.lang.Exception; descriptor: (I)V flags: Code: stack=2, locals=2, args_size=2 0: iload_1 1: ifne 12 4: new #2 // class java/lang/Exception 7: dup 8: invokespecial #3 // Method java/lang/Exception."<init>":()V 11: athrow 12: return
1) 其中new指令在java堆上为Exception对象分配内存空间,并将地址压入操作数栈顶;
2) 然后dup指令为复制操作数栈顶值,并将其压入栈顶,也就是说此时操作数栈上有连续相同的两个对象地址;
3) invokespecial指令调用实例初始化方法<init>:()V,注意这个方法是一个实例方法,所以需要从操作数栈顶弹出一个this引用,也就是说这一步会弹出一个之前入栈的对象地址;
4) athrow指令从操作数栈顶取出一个引用类型的值,并抛出;
5) 最后由return指令结束方法。
从上面的五个步骤中可以看出,需要从栈顶弹出两个实例对象的引用,这就是为什么会在new指令下面有一个dup指令,其实对于每一个new指令来说一般编译器都会在其下面生成
一个dup指令,这是因为实例的初始化方法肯定需要用到一次,然后第二个留给程序员使用,例如给变量赋值,抛出异常等,如果我们不用,那编译器也会生成dup指令,在初始化方法调用完成后再从栈顶pop出来。例如我们仅仅创建一个对象而不做任何操作,例如:
void cantBeZero(int i) throws Exception{ new Exception(); }
上面的代码仅仅创建了一个Exception对象,而没有做任何操作。
其编译后的字节码指令如下:
void cantBeZero(int) throws java.lang.Exception; descriptor: (I)V flags: Code: stack=2, locals=2, args_size=2 0: new #2 // class java/lang/Exception 3: dup 4: invokespecial #3 // Method java/lang/Exception."<init>":()V 7: pop 8: return
也会生成一个dup指令,只不过在调用完实例初始化方法后,将重复的实例引用又pop出栈了。不过这种情况基本不会出现在我们的代码中,因为我们创建的每一个对象都应该是有用的。
通过上面的例子你应该比较清楚的理解了为什么创建对象时总会有一个dup指令了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Springboot注入成员变量HttpServletRequest的原理分析
这篇文章主要介绍了Springboot注入成员变量HttpServletRequest的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-05-05详解springboot采用多数据源对JdbcTemplate配置的方法
在本篇文章中我们给大家详细分享了springboot采用多数据源对JdbcTemplate配置的方法,有需要的朋友们可以学习参考下。2018-10-10SpringBoot ApplicationListener事件监听接口使用问题探究
这篇文章主要介绍了SpringBoot ApplicationListener事件监听接口使用问题,自定义监听器需要实现ApplicationListener接口,实现对应的方法来完成自己的业务逻辑。SpringBoot Application共支持6种事件监听2023-04-04
最新评论