JVM指令
本篇指令码表,参考自ASM文档手册,如果你对asm感兴趣,可到ASM官网下载手册学习。
一、本地变量操作指令(I,L,F,D,A这些前缀表示对int,long,float,double,引用进行操作)
本地变量指令集 |
|
指令 |
意义 |
ILOAD_n(0~3), LLOAD_n(0~3), FLOAD_n(0~3), DLOAD_n(0~3) 超过三的 直接 xLoad n,如ILOAD 4,LLOAD 5 |
将局部变量表中第n个槽的(int|long|float|double)类型变量推送到操作数栈 |
ALOAD_n(0~3) 超过3的 ALOAD n,如:ALOAD 5 |
将引用类型的局部变量第n个槽的推送到操作数栈 |
ISTORE_n(0~3), LSTORE_n(0~3), FSTORE_n(0~3), DSTORE_n(0~3) 超过三的xSTORE n |
将操作数栈顶的(int|long|float|double)类型值弹出存到局部变量表的第n个槽中 |
ASTORE_n(0~3) 超过3的 ASTORE n |
将栈顶引用类型的值存到局部变量表中的第n个槽中 |
IINC var incr 将局部变量表中的第var个变量增加incr,并把新值存到局部变量表
本地变量操作表对应的下标是从0开始的,比如下面一段程序
public void print(int age) {
int a = age;
a++;
}
对应的字节码文件
stack=1, locals=3, args_size=2//这里的参数为什么是2,因为参数里面有个this,这个this是隐藏的,在JVM中是以参数的形式传递进去的
iload_1//将局部变量表中的第1个槽,也就是age这个值,0是this,压入操作数栈栈顶
istore_2//将操作数栈顶的值,这里就是age,存到局部变量表的第二个槽,也就是a
iinc 2, 1//将局部变量表中的第二个槽的a加1
return//方法返回
注意,如果局部变量中有long或者double类型的值,那么会占用局部变量两个槽,如有局部变量int age,long l, double d, short s, byte b,那么对应的槽应该是1,2,4,6,7
byte,short,char,int,boolean类型的操作指令统一使用ILOAD或者ISTORE这些指令
二、栈操作指令
指令 栈操作前 栈操作后
POP |
... , v |
... (v被弹出) |
POP2 |
... , v1 , v2 |
... (v1和v2被弹出) |
... , w |
... (w表示占用两个槽的变量,如long,double之类) |
|
DUP |
... , v |
... , v , v (复制一份) |
DUP2 |
... , v1 , v2 |
... , v1 , v2 , v1 , v2 (复制栈中的两个值) |
... , w |
... , w, w (复制一个long,double型的) |
|
SWAP |
... , v1 , v2 |
... , v2 , v1 交换 |
DUP_X1 |
... , v1 , v2 |
... , v2 , v1 , v2 复制栈顶值v2,并弹出v1,v2,然后压入v1,v2 |
DUP_X2 |
... , v1 , v2 , v3 |
... , v3 , v1 , v2 , v3 复制v3,并将弹出的3个值入栈 |
... , w , v |
... , v , w , v 复制v,并将复制的两个值入栈(W占两槽) |
|
DUP2_X1 |
... , v1 , v2 , v3 |
... , v2 , v3 , v1 , v2 , v3 复制两个值,并将弹出的3个值入栈 |
... , v , w |
... , w , v , w 复制2个值,并将弹出的两个值入栈,w占两个槽 |
|
DUP2_X2 |
... , v1 , v2 , v3 , v4 |
... , v3 , v4 , v1 , v2 , v3 , v4 复制2值,将弹出的4个值入栈 |
... , w , v1 , v2 |
... , v1 , v2 , w , v1 , v2 复制2值,将弹出的三个值入栈 |
|
.... , v1 , v2 , w |
... , w , v1 , v2 , w 复制1个值,将弹出的3个值入栈 |
|
... , w1 , w2 |
... , w2 , w1 , w2 复制1个值,将弹出的1个值入栈 |
举个例子
public void print(int age, String name) {
this.age = age;
this.name = name;
}
对应的字节码指令
aload_0 //将this入栈
dup //复制一个this
aload_1 //将age入栈
putfield #n //给age复制,这里的n表示一个数字,#n表示索引,对应常量池中的常量
aload_2 //将name入栈
putfield #n //给name复制
三、常量操作
ICONST_n (−1 ≤ n ≤ 5) |
... |
... , n 将整型常量n入栈 |
LCONST_n (0 ≤ n ≤ 1) |
... |
... , nL 将长整型常量n入栈 |
FCONST_n (0 ≤ n ≤ 2) |
... |
... , nF 将float常量入栈 |
DCONST_n (0 ≤ n ≤ 1) |
... |
... , nD 将double常量入栈 |
BIPUSH b, −128 ≤ b < 127 |
... |
... , b 将byte常量入栈 |
SIPUSH s, −32768 ≤ s < 32767 |
... |
... , s 将短整型入栈 |
LDC cst (int, float, long, double, String or Type) |
... |
... , cst 将常量池中值入栈 |
ACONST_NULL |
... |
... , null 将null值入栈 |
如:public void print(){
int a1 = 1; //ICONST_1将1入栈
//ISTORE_1 将1存入局部变量表1中,即a1
int a2 = 10; //BIPUSH 10
//ISTORE 2
int a3 = 100; // SIPUSH 100
//ISTORE 3
float a4 = 123f; //LDC #4这个#4是引用了常量池里的值,123
//FLOAD 4
}
四、算术和逻辑操作指令
IADD, LADD, FADD, DADD |
... , a , b |
... , a + b 将栈顶的两个值相加,并把结果入栈 |
ISUB, LSUB, FSUB, DSUB |
... , a , b |
... , a - b |
IMUL, LMUL, FMUL, DMUL |
... , a , b |
... , a * b |
IDIV, LDIV, FDIV, DDIV |
... , a , b |
... , a / b |
IREM, LREM, FREM, DREM |
... , a , b |
... , a b |
INEG, LNEG, FNEG, DNEG |
... , a |
... , -a |
ISHL, LSHL |
... , a , n |
... , a << n |
ISHR, LSHR |
... , a , n |
... , a >> n |
IUSHR, LUSHR |
... , a , n |
... , a >>> n |
IAND, LAND |
... , a , b |
... , a & b |
IOR, LOR |
... , a , b |
... , a | b |
IXOR, LXOR |
... , a , b |
... , a ^ b |
LCMP |
... , a , b |
... , a == b ? 0 : (a < b ? -1 : 1) |
FCMPL, FCMPG |
... , a , b |
... , a == b ? 0 : (a < b ? -1 : 1) |
DCMPL, DCMPG |
... , a , b |
... , a == b ? 0 : (a < b ? -1 : 1) |
五、转换
I2B |
... , i |
... , (byte) i |
I2C |
... , i |
... , (char) i |
I2S |
... , i |
... , (short) i |
L2I, F2I, D2I |
... , a |
... , (int) a |
I2L, F2L, D2L |
... , a |
... , (long) a |
I2F, L2F, D2F |
... , a |
... , (float) a |
I2D, L2D, F2D |
... , a |
... , (double) a |
CHECKCAST class |
... , o |
... , (class) o |
六、对象,字段,方法操作
NEW class |
... |
... , new class |
GETFIELD c f t |
... , o |
... , o.f |
PUTFIELD c f t |
... , o , v |
... |
GETSTATIC c f t |
... |
... , c.f |
PUTSTATIC c f t |
... , v |
... |
INVOKEVIRTUAL c m t |
... , o , v1 , ... , vn |
... , o.m(v1, ... vn) |
INVOKESPECIAL c m t |
... , o , v1 , ... , vn |
... , o.m(v1, ... vn) |
INVOKESTATIC c m t |
... , v1 , ... , vn |
... , c.m(v1, ... vn) |
INVOKEINTERFACE c m t |
... , o , v1 , ... , vn |
... , o.m(v1, ... vn) |
INVOKEDYNAMIC m t bsm |
... , o , v1 , ... , vn |
... , o.m(v1, ... vn) |
INSTANCEOF class |
... , o |
... , o instanceof class |
MONITORENTER |
... , o |
... |
MONITOREXIT |
... , o |
... |
七、数组操作
NEWARRAY type (for any primitive type) new基本类型的数组 |
... , n 数组长度 |
... , new type[n] new出来的数组引用 |
ANEWARRAY class new引用类型的数组 |
... , n 数组长度 |
... , new class[n] |
MULTIANEWARRAY [...[t n 多维数组 |
... , i1 , ... , in 各维长度 |
... , new t[i1]...[in]... |
BALOAD, CALOAD, SALOAD 将指定下标的值入栈 |
... , o , i i下标,o数组 |
... , o[i] |
IALOAD, LALOAD, FALOAD, DALOAD |
... , o , i |
... , o[i] |
AALOAD |
... , o , i |
... , o[i] |
BASTORE, CASTORE, SASTORE |
... , o , i , j |
... |
IASTORE, LASTORE, FASTORE, DASTORE |
... , o , i , a |
... |
AASTORE |
... , o , i , p |
... |
ARRAYLENGTH |
... , o |
... , o.length |
八、跳转语句
IFEQ |
... , i |
... |
jump if i == 0 |
IFNE |
... , i |
... |
jump if i != 0 |
IFLT |
... , i |
... |
jump if i < 0 |
IFGE |
... , i |
... |
jump if i >= 0 |
IFGT |
... , i |
... |
jump if i > 0 |
IFLE |
... , i |
... |
jump if i <= 0 |
IF_ICMPEQ |
... , i , j |
... |
jump if i == j |
IF_ICMPNE |
... , i , j |
... |
jump if i != j |
IF_ICMPLT |
... , i , j |
... |
jump if i < j |
IF_ICMPGE |
... , i , j |
... |
jump if i >= j |
IF_ICMPGT |
... , i , j |
... |
jump if i > j |
IF_ICMPLE |
... , i , j |
... |
jump if i <= j |
IF_ACMPEQ |
... , o , p |
... |
jump if o == p |
IF_ACMPNE |
... , o , p |
... |
jump if o != p |
IFNULL |
... , o |
... |
jump if o == null |
IFNONNULL |
... , o |
... |
jump if o != null |
GOTO |
... |
... |
jump always |
TABLESWITCH |
... , i |
... |
jump always |
LOOKUPSWITCH |
... , i |
... |
jump always |
九、return
IRETURN, LRETURN, FRETURN, DRETURN |
... , a |
|
ARETURN |
... , o |
|
RETURN |
... |
|
ATHROW |
... , o |
十、泛型
如:public class Test<T> ==> <T:Ljava/lang/Object;>
public class Test<T> extends ArrayList<E> ==> <T:Ljava/lang/Object;>Ljava/util/ArrayList<TE;>;
static <T> Class<? extends T> m (int n) ==> <T:Ljava/lang/Object;>(I)Ljava/lang/Class<+TT;>;
List<E> ==> Ljava/util/List<TE;>;
List<?> ==> Ljava/util/List<*>;
List<? extends Number> ==> Ljava/util/List<+Ljava/lang/Number;>;
List<? super Integer> ==> Ljava/util/List<-Ljava/lang/Integer;>;
List<List<String>[]> ==> Ljava/util/List<[Ljava/util/List<Ljava/lang/String;>;>;
HashMap<K, V>.HashIterator<K> ==> Ljava/util/HashMap<TK;TV;>.HashIterator<TK;>;
注意:如果是定义定义泛型,比如class Test<T>,方法中的<T>这类T,在写泛型签名的时候应当写成T:Ljava/lang/Object;而不是TT;在其他非定义泛型的位置,写成TT;
十一、描述符表
java类型 | 类型描述符 |
boolean | Z |
char | C |
byte | B |
short | S |
int | I |
long | J |
float | F |
double | D |
Object | Ljava/lang/Object; |
int[] | [I |
Object[][] | [[Ljava/lang/Object; |
十二、方法描述符
方法 | 方法描述符 |
void m(int i, float f) | (IF)V |
int m(Object o) | (Ljava/lang/Object;)I |
int[] m(int i, String s) | (ILjava/lang/String;)I |
Object m(int[] i) | ([I)Ljava/lang/Object; |
JVM指令的更多相关文章
- [转]JVM指令详解(上)
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 本文主要记录一些JVM指令,便于记忆与查阅. 一.未归类系列A 此系列暂未归类. 指令码 助记符 ...
- Java并发编程(五)JVM指令重排
我是不是学了一门假的java...... 引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序:在特定情况下,指令重排将会给我们的程序带来不确定的结果.. ...
- JVM 指令讲解
挺有意思的 转载记录下 转载自 https://www.cnblogs.com/f1194361820/p/8524666.html 原作者: 房继诺 JVM 指令 1.Demo 2.Clas ...
- JVM指令助记符
以下只是JVM指令助记符,关于JVM指令的详细内容请阅读<JVM指令详解> 变量到操作数栈:iload,iload_,lload,lload_,fload,fload_,dload,dlo ...
- JVM指令手册
JVM指令大全 常量入栈指令 指令码 操作码(助记符) 操作数 描述(栈指操作数栈) 0x01 aconst_null null值入栈. 0x02 iconst_m1 -1(int)值入栈. 0x03 ...
- Javap与JVM指令
一.javap命令简述 javap是jdk自带的反解析工具.它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令).本地变量表.异常表和代码行偏移量映射表.常量池等等信息.当 ...
- jvm指令手册查看
00-JVM指令手册 栈和局部变量操作 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 ...
- 深入JVM(一)JVM指令手册
本文按照如下思维导图组织 1. 栈和局部变量操作 1.1 将常量压入栈的指令 aconst_null 将null对象引用压入栈iconst_m1 将int类型常量-1压入栈iconst_0 将int类 ...
- 2.1 附录--JVM指令手册
栈和局部变量操作 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 iconst_1 将 ...
- JVM 指令
1.Demo 2.Class 文件说明 2.1 Class文件结构 2.2 jvm type, method signature 2.3 泛型表示 3.方法说明 3.1 方法结构 3.1.1 Thre ...
随机推荐
- hgoi#20190513
T1-Felicity is Coming! 神奇宝贝的进化方案是一个全排列,假设有三种宝可梦,那么对应就可以有: (1,2,3)(1,3,2)(2,1,3)(2,3,1)(3,1,2)(3,2,1) ...
- JavaScript学习笔记(2)
常用对象 Boolean Number String Array 数组 Date 日期 Math 数字 RegExp 正则 Global 全局 函数 var m = function(){} 事件 o ...
- 7天入门Linux
经过一个星期学习,Linux终于入门了,在这里小记下~ =====================分割线============================= Ubuntu常用命令: ctrl+s ...
- cat more less 命令混用
在Linux系统中有三种命令可以用来查阅全部的文件,分别是cat.more和less命令.它们查阅文件的使用方法也比较简单都是 命令 文件名 ,但是三者又有着区别. 1.cat命令可以一次显示整个文件 ...
- POJ 2679:Adventurous Driving(SPFA+DFS)
http://poj.org/problem?id=2679 Adventurous Driving Time Limit: 1000MS Memory Limit: 65536K Total S ...
- cur.execute(sql,args)和cur.execute(sql)的区别
轉:https://blog.csdn.net/mjjyszazc/article/details/88932664 方式一: userid = “123”sql = “select id,name ...
- C++中 / 和 % 在分离各位时的妙用
在学习c++的过程中,我们一般用 / 和 % 来分解数字的各个位 取整 (/) 比如1234 / 10 等于 123.4,这相当于把前三位分解出来了 取余(%) 比如 12345 的分解方法 个位:1 ...
- 浅谈SpringBoot
关于SpringBoot有哪些特性,SpringBoot官网是这么描述的: Features Create stand-alone Spring applications Embed Tomcat, ...
- Flutter学习笔记(6)--Dart异常处理
如需转载,请注明出处:Flutter学习笔记(6)--Dart异常处理 异常是表示发生了意外的错误,如果没有捕获异常,引发异常的隔离程序将被挂起,并且程序将被终止: Dart代码可以抛出并捕获异常,但 ...
- Perm排列计数(新博客试水,写的不好,各路大神见谅)
B. Perm 排列计数 内存限制:512 MiB 时间限制:1000 ms 标准输入输出 题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i&l ...