什么是字节码指令?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值