前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JVM指令的速记

JVM指令的速记

作者头像
付威
发布2020-05-06 15:13:58
1K0
发布2020-05-06 15:13:58
举报
文章被收录于专栏:老付的网络博客

在学习的JVM的时候,最重要的是认识JVM的指令,JVM指令很多,为了方便记忆,可以根据前缀和功能进行分类:

例如:nop指令代表是一个空指令,JVM收到指令后,什么都不用做,等待下一个指令。


const把数据推至栈顶

const的范围从0x01–0x0f,负责把数据推送到栈顶。例如:iconst_0负责吧整型的0推送到栈顶。 fconst_0负责把float的0推送到栈顶。const可以分为以下几种类型:

iconst_:把int推送栈顶

fconst_:推送float类型栈顶

lconst_:推送long到栈顶

dconst_:提送double至栈顶

上述的为简写的前缀,后续可以跟参数,例如:iconst_0,iconst_1分别代表推送0和1至栈顶。


push常量到栈顶

这个类别中有两个指令bipushsipush,比较容易记忆:bipush推送的是-128~127之间的数据,sipush推送一个端整型的常量。


从常量池中推送至栈顶

这个类别有三个指令,ldc,ldc_w,ldc2_w三个指令。

ldc:将 int,float 或 String 型常量值从常量池中推送至栈顶

ldc_w:将 int,float 或 String 型常量值从常量池中推送至栈顶(宽索引)

ldc2_w: 将 long 或 double 型常量值从常量池中推送至栈顶(宽索引)

其中,ldc_w和ldc2_w属于宽索引指令,即指令对应的(索引值)参数为2个字节。而ldc指令对应的(索引值)参数为1个字节。


load加载指令

load指令是加载把指定的本地变量推送的至栈顶,范围是0x15~0x3a。 例如iload_0是将第一个int型的变量推送至栈顶。load指令也分为4类iloadlload,fload,dload,aload.


aload数组加载指令

aload可以理解成load的加载的数组类型,类型也基本相同,不再赘述dstore。


store 将栈顶的数据存入本地变量

store是将栈顶的栈顶的数据存入本地变量,范围0x36~0x4e。按类型的区分:

istore:将栈顶 int 型数值存入指定本地变量,

lstore:将栈顶 long 型数值存入指定本地变量,

fstore:将栈顶 float 型数值存入指定本地变量,

dstore:将栈顶 double 型数值存入指定本地变量,

astore:将栈顶引用类型数值存入指定本地变量

同样store也存在对应的数组类型astore具体逻辑类似。


栈的操作

pop:栈顶的元素弹出

pop2: 将栈顶的一个(long 或 double 类型)或两个数值(非 long 或 double 的其他类型)弹出

dup:复制栈顶的数值并压入栈

dup指令存在几个衍生的版本:

dup_x1: 复制栈顶的数值,并将两个复制的值压入栈

dup_x2:复制栈顶数值并将三个(或两个)复制值压入栈顶

dup2:复制栈顶一个(long 或 double 类型)或两个(非 long 或 double 的其他类型)数值并将复制值压入栈顶

dup2_x1:dup_x1 指令的双倍版本

dup2_x2:dup_x2 指令的双倍版本

swap:交换两个栈顶的数据,数值不能是long或者double类型


运算指令

JVM对于加减乘除和位运算都提供了不同的指令:

add:将栈顶相加并将结果压入栈顶

sub:将栈顶数值相减并将结果压入栈顶

mul:将栈顶数值相乘并将结果压入栈顶

div:将栈顶数值相除并将结果压入栈顶

rem:将栈顶数值作取模运算并将结果压入栈顶

neg:将栈顶数值取负并将结果压入栈顶

shl:将数值左移指定位数并将结果压入栈顶

shr:将数值右移(带符号)指定位数并将结果压入栈顶

ushr:将数值右移(无符号)指定位数并将结果压入栈顶

and:将栈顶两数值”按位与”并将结果压入栈顶

or:将栈顶两数值”按位或”并将结果压入栈顶

xor:将栈顶两数值”按位异或”并将结果压入栈顶

iinc:将指定 int 型变量增加指定值,常用于i++,i+=2等

运算指令同样存在类型的区别,比如iadd用于int的相加,ladd用于long的相加。


类型转换

在java中存在类型的转换,有的是隐形的,有的是显性的。

(1) 对于宽化类型转换(小范围向大范围转换),无需显式的转换指令,并且是安全的操作。各种范围从小到大依次排序: int, long, float, double。

(2)对于窄化类型转换,必须显式地调用类型转换指令,并且该过程很可能导致精度丢失。转换规则中需要特别注意的是当浮点值为NaN, 则转换结果为int或long的0。虽然窄化运算可能会发生上/下限溢出和精度丢失等情况,但虚拟机规范明确规定窄化转换U不可能导致虚拟机抛出异常。

对于转换指令比较容易记忆,在两个类型中间使用2进行分割,比如i2l是int转long ,i2f代表int 转float等,更多的请参考官方文档。


条件控制

比较指令

cmp是比较栈顶的两个元素大小的值,指令有:

cmpl:比较栈顶两数值大小, 并将结果(1, 0 或-1)压入栈顶;当其中一个数值为 NaN 时, 将-1 压入栈顶, cmpg:比较栈顶两数值大小, 并将结果(1, 0 或-1)压入栈顶;当其中一个数值为 NaN 时, 将1 压入栈顶

同样也存在类型的区别,fcmpl,dcmpl分别代表不同的浮点型和双精度类型。


控制指令

JVM的控制指令是指有条件或无条件地修改PC寄存器的值,从而达到控制流程的目标 ,共分成3类:

  • 条件分支undefined条件分支是在编程的时候使用的ifwhiledai
    • ifeq: 当栈顶值等于0的时候跳转
    • ifne:当栈顶值不等于0的时候跳转
    • iflt:当栈顶值小于0的时候跳转
    • ifge:当栈顶值大于等于0的时候跳转
    • ifgt:当栈顶值大于0的时候跳转
    • ifle:当栈顶值小于等于0的时候跳转

对于两个值的比较可以使用if_icmpeq(其中,if_是前缀,i代表int,eq代表相等),同样可以得到下面的指令:

代码语言:txt
复制
- `if_icmpcq`: 如果两个int值相等,则跳转
- `if_icmpne`: 如果两个int类型值不相等,则跳转
- `if_icmplt`: 如果一个int类型值小于另外一个int类型值,则跳转
- `if_icmpge`: 如果一个int类型值大于或者等于另外一个int类型值,则跳转
- `if_icmpgt`: 如果一个int类型值大于另外一个int类型值,则跳转
- `if_icmple`: 如果一个int类型值小于或者等于另外一个int类型值,则跳转

是否为空的时候跳转:

代码语言:txt
复制
- `ifnull` 为 null 时跳转
- `ifnonnull` 不为 null 时跳转复合条件
复合条件是
  • 无条件 无条件的跳转在实际的编程中很少使用,goto语句,在while中实际也是goto指令的作用,无条件跳转有下面三个指令: goto:无条件跳转 goto_w: 无条件跳转(宽索引) jsr:跳转至指定的 16 位 offset 位置, 并将 jsr 的下一条指令地址压入栈顶 jsr_w:同jsr,此指令为宽索引 ret:返回至本地变量指定的 index 的指令位置(一般与 jsr 或 jsr_w 联合使用)

return 方法的返回

return指令是方法的end的指令,存在的不同类型的返回值,例如ireturn返回int类型,lreturn 返回long型,return代表void的类型返回。


静态几个指令

getstatic: 获取指定类的静态域, 并将其压入栈顶

putstatic: 为指定类的静态域赋值

getfield: 获取指定类的实例域, 并将其压入栈顶

putfield: 为指定类的实例域赋值


方法调用

方法调用类型主要有5种类型:

invokevirtual: 调用实例方法

invokespecial :调用超类构建方法, 实例初始化方法, 私有方法

invokestatic: 调用静态方法

invokeinterface:调用接口方法

invokedynamic:调用动态方法


数组指令

newarray:创建一个指定的原始类型(如 int, float, char 等)的数组,并将其引用值压入栈顶

anewarray: 创建一个引用型(如类, 接口, 数组)的数组, 并将其引用值压入栈顶

arraylength: 获取数组的长度值并压入栈顶

multianewarray: 创建指定类型和指定维度的多维数组, 并将其引用压入栈顶


对象指令

new: 创建一个实例对象。

checkcast:检验类型转换, 检验未通过将抛出 ClassCastException

instanceof:检验对象是否是指定类的实际, 如果是将 1 压入栈顶, 否则将 0 压入栈顶


异常

athrow:将栈顶的异常抛出

并发指令

在synchronized关键字的时候,底层的指令是monitorentermonitorexit

monitorenter:获得对象的锁, 用于同步方法或同步块

monitorexit:释放对象的锁, 用于同步方法或同步块

代码语言:txt
复制
(本文完) 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • const把数据推至栈顶
  • push常量到栈顶
  • 从常量池中推送至栈顶
  • load加载指令
  • aload数组加载指令
  • store 将栈顶的数据存入本地变量
  • 栈的操作
  • 运算指令
  • 类型转换
  • 条件控制
    • 比较指令
      • 控制指令
      • return 方法的返回
      • 静态几个指令
      • 方法调用
      • 数组指令
      • 对象指令
      • 异常
      • 并发指令
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档