javap—跟在new指令屁股后面的dup指令

每当我查看反编译结果时,经常会看到 dup 字节码指令跟在 new 字节码指令之后,又不知道它是干嘛的,很影响阅读,所以就有了这篇博客~

JVM 中的字节码指令操作是基于操作数栈的,栈操作一个数据只能通过先出栈计算,再将结果压栈的方式。操作数栈主要用于保存执行过程的中间结果:配合局部变量表,将中间结果保存在变量槽中;需要使用局部变量时,读取局部变量表对应变量槽中的元素压入栈顶再出栈。

以下代码创建了 CreateObjectTest 对象,并使用局部变量 createObjectTest 保存实例的引用。

public class CreateObjectTest {
    public static void main(String[] args) {
        CreateObjectTest createObjectTest = new CreateObjectTest();
    }
}

第一段代码反编译结果:

Code:
      stack=2, locals=2, args_size=1
         0: new           #2  new 关键字,在堆中创建 CreateObjectTest 实例,并将该对象的引用压入操作数栈顶                // class object/create/CreateObjectTest
         3: dup 复制一份栈顶元素并压栈
         4: invokespecial #3   调用无参构造              // Method "<init>":()V
         7: astore_1 将栈顶元素存入变量槽18: return

第一步 JVM 执行 new 指令,在堆中开辟内存空间并创建 CreateObjectTest 对象,并将对象对应的引用压入栈顶。

第二步 dup 复制一份栈顶元素并压栈。这里为什么要复制一份呢?往下看

第三步 invokespecial 指令弹出栈顶元素,调用 CreateObjectTest 的无参构造方法,进行对象实例化。
因为无参构造方法是实例方法,jvm 会自动传入调用该实例方法的对象,实例方法中可以通过 this 关键字访问该对象,且该对象位于局部变量表0号变量槽中。

第四步 astore_1 将栈顶元素存入变量槽1中,变量槽0被 String[] args 占用。
这时候 dup 的作用体现了:原栈顶数据 A1(对象引用),经过 dup 指令,栈顶变为 A2。调用无参构造,A2 出栈,A1重新变成栈顶。然后 astore_1 指令将 A1 存入变量槽1中。如果没有 dup 指令,那么数据 A1 在调用无参构造时出栈,astore_1 无法找到数据。

以下代码创建了 CreateObjectTest 对象,没有保存实例的引用。

public class CreateObjectTest {
    public static void main(String[] args) {
        new CreateObjectTest();
    }
}        

实例的引用不会被用到第二次,那么是否就不用执行 dup 指令了呢?

Code:
      stack=2, locals=1, args_size=1
         0: new           #2                 // class object/create/CreateObjectTest
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: pop
         8: return 

还是执行了 dup 指令,在调用完无参构造后将多余的数据弹出栈顶。

所以我们在任何时刻使用 new 关键字创建对象时,查看对应的反编译结果,都能看到 new + dup + invokespecial 的组合

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值