字节码指令

字节码指令

PS : 本文乃学习整理参考而来


字节码指令简介
Java虚拟机的指令一个字节长度的、代表着某种特定含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成。 由于Java虚拟机采用面向操作数栈不是寄存器的架构,所以大多数的指令都不包含操作数,只有一个操作码。由于限制了Java虚拟机操作码长度为一个字节,所以指令集的操作码总数不可能超过256条。


字节码数据类型:大部分与数据类型相关的字节码指令,他们的操作码助记符中有特殊的字符来表明专门为哪种数据类型服务i代表int,l代表longs代表short等等。大部分指令都没有支持整型类型****bytecharshort以及boolean类型。编译器会在编译器或运行期byteshort类型的数据带符号扩展为相应的int类型,将booleanchar类型数据零位扩展为相应的int类型数据。与之类似在操作boolean、byte、short和char类型的数组时,也会转换为只用对应的int类型的字节码指令来处理。因此大多数对于上述类型数据的操作,实际上都是使用相应int类型作为运算类型。


加载存储指令助记符
加载和存储指令用于将数据栈帧中的局部变量表操作数栈之间来回传输
load将一个局部变量加载到操作栈iloadlloadfload等。
store将一个数值从操作数栈存储到局部变量表istorelstorefstore等。
将一个常量加载到操作数栈:bipush、sipush、ldc等


运算指令助记符
加法指令iadd、ladd、fadd、dadd
减法指令isub、lsub、fsub、dsub
等等。

在Java虚拟机规范中定义了在除法指令(idivldiv)以及求余指令(iremlrem)中当出现除数为零时会导致虚拟机抛出ArithmeticException其余整型运算场景都不应该抛出运行时异常。


类型转换指令
Java虚拟机直接支持以下数值类型的宽化类型转换
int类型到longfloat或者double
long类型到floatdouble
float类型到double
相对的,处理窄化类型转换时,必须显示的使用转换指令来完成,这些转换指令包括i2b、i2c、l2i、f2i、d2i等等


对象创建与访问指令
创建类实例的指令:new
创建数组的指令:newarayanewarray
访问类字段(static字段)和实例字段(非static字段)的指令:getfieldputfieldgetstaticputstatic
把一个数组元素加载到操作数栈的指令:baload、caload、saload、iaload等等
操作数栈的值存储到数组元素中的指令:bastore、castore、sastore、iastore等等
查数组长度的指令:arraylength
查实例类型的指令:instanceofcheckcast


操作数栈管理指令:
将操作数栈顶一个或两个元素出栈:pop、pop2
复制栈顶一个或两个数值将复制值或者双份的复制值重新压如栈顶dupdup2
将栈最顶端的两个数值互换:swap


控制转移指令:
控制转移指令可以让Java虚拟机有条件无条件从指定的位置执行而不是控制转移指令的下一条指令继续执行程序,
可以认为控制转移指令就是在有条件或无条件的修改PC寄存器的值
条件分支ifeqifnull
无条件分支gotogoto_wjsrret


方法调用和返回指令:
invokevirtual指令:用于调用对象的实例方法
invokeinterface指令:用于调用接口方法,他会在运行时搜索一个实现了这个接口的对象,找出适合的方法进行调用。
invokespecial指令:用于调用一些需要特殊处理的实例方法,包括实例初始化方法私有方法父类方法
invokestatic指令:用于调用类方法(static方法)。


异常处理指令:
在Java程序中显示抛出异常的操作(throw)都有athrow指令来实现,除了用throw语句显示抛出异常情况之外,Java虚拟机规范还规定了许多运行时异常会在其他Java虚拟机指令检测到异常状况时自动抛出。例如,在整数运算中,当除数为零时,虚拟机会抛出ArithmeticException异常。在Java虚拟机中,处理异常(catch)不是由字节码来实现的,而是采用异常表(Code属性中)完成的。


同步指令:
Java的同步分为方法级同步方法内部一段指令序列同步(部分代码),这两种同步结构都是使用管程Monitor)来支持的。
方法级的同步无需通过字节码指令来控制,他的实现在方法调用和方法返回中,虚拟机能通过Class结构表中通过方法表结构中的access_flags中的ACC_SYNCHRONIZED标志得知一个方法是否声明为同步方法。当方法调用时调用指令将会检查方法的该标志位是否被设置了,如果为真执行线程就要先成功持有管程然后才能执行方法,最后当方法完成时(无论是正常完成还是非正常)释放管程。在方法执行期间,执行线程持有了管程,其他任何线程都无法再获得到管程,如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那么这个同步方法所持有的管程在异常抛出到同步方法之外自动释放

指令集序列同步(部分代码同步):Java虚拟机使用monitorentermonitorexit两条指令来支持synchronized关键字的语义。在执行代码前monitorenter开始同步,在执行完代码退出以前monitorexit退出同步。


更多详细内容推荐参考:[Java虚拟机字节码指令]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值