深入分析javaweb技术内幕之在Javap生成的jvm指令详解

与类相关的JVM指令(通过javap -c 后面追加class文件目录即可看到)

指令                                     参数                                                        解释

checkcast    class校验类型转换,校验未通过将抛出ClassCastException
getfieldclass/field desc获取指定类的实例域,并将其值压入栈顶
getstaticclass/field desc获取指定类的静态域,并将其压入栈顶
instanceofclass检验对象是否是指定的类的实例,如果是,则将1压入栈顶,否则将0压入栈顶
newclass

创建一个对象,并将其引用值压入栈顶

示例代码:checkcast:

        Map<String, Object> map = new HashMap<>();
        map.put("lt", liuzheTest);
        LiuzheTest ts = (LiuzheTest) map.get("lt");

getfield:

    public int getT() {
        return t;
    }

instanceof:if (o instanceof LiuzheTest)

与方法相关的JVM指令:

指令操作数解释
invokeinterfaceclass/method desc调用接口方法
invokespecialclass/method desc调用超类构造方法、实例初始化方法或私有方法

invokestatic

class/method desc调用静态方法
invokevirtualclass/method desc调用实例方法
dup:将当前栈顶元素复制一份,并压入战中。

pop:从当前栈顶出栈一个元素。

pop2:从栈顶的一个long或double类型的或两个其他数据从栈顶弹出

swap:将栈顶两个非long或者double类型的数值交换

指令操作数解释
aloadn将当前本地变量n放入栈顶中,变量n是一个引用,如aload_1,aload_2,aload_3
astoren将栈顶元素存入本地变量n中,变量n是一个引用
dloadn将当前本地变量n放入栈顶中,变量n是一个double类型
dstoren将栈顶元素存入本地变量n中,变脸n是一个double类型
floadn将当前本地变量n放入栈顶中,变量n是一个fload类型
fstoren将栈顶元素存入本地变量n中,变量n是一个float类型
iincn increment将指定int型变量增加指定值
iloadn将当前本地变量n放入栈顶中,变量n是一个int类型
lloadn将当前本地变量n放入栈顶中,变量n是一个long类型
istoren

将栈顶元素存入本地变量n中,变量n是一个long类型

3.与运算相关



6.与java数据类型转换相关


7.与java同步操作相关

指令操作数解释
monitorenter 获得对象的锁,用于同步方法或同步块
monitorexit 释放对象的锁,用于同步方法或同步块

8.与java数组操作相关:


class字节码文件,通过javap -v 可以打印class字节码。这个就不演示了。不过在生成的字节码中,有两个地方需要解释一下:

一个是LineNumberTable,另一个是LocalVariableTalbe。

LineNumberTable

在LineNumberTable下面包含多个line a:b,每个line表示这个方法中的一行。其中a表示的是在这个方法中的一行代码在这个类文件中的第几行,而b是指这行代码的第一条JVM指令的pc偏移量。如在上面的main方法中有两行代码,


LocalVariableTable

LineNumberTable包含5个属性,分别是Start,Length,Slot,Name和Signature。其中,Start和Length表示该变量的有效作用域的偏移地址;Start表示该变量被赋值到某个Slot中的指令(xstore_x指令)的下一条指令的偏移地址:Length表示该变量作用域总共占用的指令数对应的偏移量,所以一个变量的作用域就是[Start,Start+Length];Slot和Name分别表示该变量占用的Slot编号和该变量的名称,Signature表示该变量的类型。下面结合一个例子再介绍以下它们的含义。


上图对应的字节码和LineNumberTable如下:


在这个方法中有6个变量,共使用了4个Slot。变量j在lstore4这条指令中被首次赋值,所以它的Start从下一条指令开始,也就是iinc 3 -1指令的偏移量是21,而Length是3,说明这个变量的作用域是[21,24],偏移量24对应的指令是goto14,从源码看变量j的有效范围与在while循环体内是吻合的。

从上面的LocalVariableTalbe中还能发现,变量i和b使用的都是Slot3,它们为什么能公用Slot区?变量i的作用域是[14,27],变量b的作用域是[33,40],可以发现它们的作用域是不重合的,而Slot的使用规则正是当变量作用域不重合时可以重复使用。这也解释了为什么有6个本地变量,但是实际上只使用了4个Slot。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值