java 数组求和_Java字节码介绍【三】

本文为翻译的文章,作者Mahmoud Anouti,原文:https://dzone.com/articles/introduction-to-java-bytecode

方法调用:

在之前的示例中,仅有一个main方法。假设我们需要对于变量c做更精细的计算,我们决定把它放在一个新的方法中,名字是calc:

013ae99e4b7d21072fcc28de73eac1b4.png

让我们看看生成的字节码:

0160d14a20f9108d76bd380b8c5db313.png

main方法代码的唯一区别是:我们不是使用iadd指令,而是invokestatic指令,它调用了静态方法calc。需要注意的关键点是,操作数栈包含了两个传递给calc方法的参数。换句话说,调用方法准备好所有被调方法需要的参数,把这些参数以正确的顺序加入操作数栈顶。invokestatic(或者一个我们在后面会看到的相似的调用指令)接下来会把这些参数出栈,一个新的为被调用方法准备的栈帧会被创建,参数会放置在它的局部变量数组中。

通过观察地址信息,我们也注意到invokestatic指令占用了3个字节,从6跳到了9。这是因为,与我们目前看到的所有指令不同的是,invokestatic包含了两个额外的字节来构建对于被调用方法的引用(除了操作符)。javap把这个引用显示为#2,它是calc方法的符号引用,被前面提到的常量池所解析。

其它新的信息显然就是calc方法自身的代码。它首先把第一个整型参数加入操作数栈顶(iload_0)。下一条指令i2d通过扩展转换把它转成double类型。double型的结果替换了操作数栈顶的值。

下一条指令把一个double型常量2.0d(从常量池获取)加入操作数栈。然后静态方法Math.pow被调用,到目前为止准备好的两个操作数值是其参数(calc的第一个参数和常量2.0d)。当方法Math.pow返回时,它的结果会存放在调用方的操作数栈中。如下图所示。

04060a3311d264fea9b7adc935342a90.png

同样的过程适用于对Math.pow(b, 2)的计算:

c03a852751545b742dd5917fb436c33b.png

下一条指令dadd从栈顶取出两个中间计算结果,进行求和,把结果放回栈顶。最后,invokestatic 在求和结果上调用Math.sqrt,并且使用缩小转换把double转成了int(d2i)。生成的整数返回到main方法中,保存回变量c(istore_3)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值