附录B 常见Java字节码指令表
这是ASM中所有的常量操作数,在ASM中用其指代JVM指令,可以用ACC_PUBLIC这样更有可读性的名字代替,也可以用数字表示
public interface Opcodes {
// ASM的版本,以下表述均合法
int ASM4 = 4 << 16 | 0 << 8 | 0;
int ASM5 = 5 << 16 | 0 << 8 | 0;
// Java版本,需要限定Java版本时使用,至于为什么是45-52不得而知
int V1_1 = 3 << 16 | 45;
int V1_2 = 0 << 16 | 46;
int V1_3 = 0 << 16 | 47;
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
// 所有的访问修饰关键字,例如public,private之类
int ACC_PUBLIC = 0x0001; // class, field, method
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter
int ACC_DEPRECATED = 0x20000; // class, field, method //ACC_DEPRECATED代指@Deprecated注解标注的类或字段,方法
//基本类型
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
// tags for Handle
int H_GETFIELD = 1; //获取字段
int H_GETSTATIC = 2; //获取静态变量
int H_PUTFIELD = 3; //指定字段
int H_PUTSTATIC = 4; //指定静态变量
int H_INVOKEVIRTUAL = 5; //调用对象实例方法
int H_INVOKESTATIC = 6; //调用静态方法
int H_INVOKESPECIAL = 7;//调用实例初始化方法(<init>方法),private或父类方法
int H_NEWINVOKESPECIAL = 8;
int H_INVOKEINTERFACE = 9;//调用接口方法
// stack map frame types
//每调用一次方法,便会为其开辟栈空间,生成栈帧,以下都是栈帧相关操作
/**
* Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
*/
int F_NEW = -1;
/**
* Represents a compressed frame with complete frame data.
*/
int F_FULL = 0;
/**
* Represents a compressed frame where locals are the same as the locals in
* the previous frame, except that additional 1-3 locals are defined, and
* with an empty stack.
*/
int F_APPEND = 1;
/**
* Represents a compressed frame where locals are the same as the locals in
* the previous frame, except that the last 1-3 locals are absent and with
* an empty stack.
*/
int F_CHOP = 2;
/**
* Represents a compressed frame with exactly the same locals as the
* previous frame and with an empty stack.
*/
int F_SAME = 3;
/**
* Represents a compressed frame with exactly the same locals as the
* previous frame and with a single value on the stack.
*/
int F_SAME1 = 4;
//以下都是JVM指令,将常量名小写就是其对应的JVM指令,例如ACONST_NULL小写就是aconst_null指令
//1,2,3,4,5等对应的也是真实的JVM操作码,186对应ba
//Insn是instruction的缩写,可以深入到方法内部去修改其变量和操作
//CONST指常量,I指int,F指float,D指double,C指char,S指short,L指long,B指byte
//ADD,MIN,MUL,DIV指加减乘除,IADD就是两个int相加
//AND,OR,XOR指按位与,按位或,按位或非
//2指的是to,例如I2B指int to byte
//LOAD指入栈,STORE指出栈,ALOAD指任意局部变量入栈
//RETURN指返回
int NOP = 0; // visitInsn
int ACONST_NULL = 1; // -将一个空引用推到栈顶
int ICONST_M1 = 2; // -将-1加载到栈顶
int ICONST_0 = 3; // -将0加载到栈顶
int ICONST_1 = 4; // -将1加载到栈顶
int ICONST_2 = 5; // -将2加载到栈顶
int ICONST_3 = 6; // -将3加载到栈顶
int ICONST_4 = 7; // -将4加载到栈顶
int ICONST_5 = 8; // -将5加载到栈顶(以上都是int)
int LCONST_0 = 9; // -将0L加载到栈顶
int LCONST_1 = 10; // -将1L加载到栈顶
int FCONST_0 = 11; // -将0F加载到栈顶
int FCONST_1 = 12; // -将1F加载到栈顶
int FCONST_2 = 13; // -将2F加载到栈顶
int DCONST_0 = 14; // -将0D加载到栈顶
int DCONST_1 = 15; // -将1D加载到栈顶
int BIPUSH = 16; // visitIntInsn -将byte值作为int推到栈顶
int SIPUSH = 17; // -将short作为int推到栈顶
int LDC = 18; // visitLdcInsn -从常量池 (可以是String, int, float, Class, java.lang.invoke.MethodType, or java.lang.invoke.MethodHandle) 中将一个#index常量推到栈顶
int ILOAD = 21; // visitVarInsn //从局部变量表中加载int值到栈顶
int LLOAD = 22; // -从局部变量表加载long到栈顶
int FLOAD = 23; // -从局部变量表加载float到栈顶
int DLOAD = 24; // -从局部变量表加载double到栈顶
int ALOAD = 25; // -从局部变量表加载Object引用到栈顶
int IALOAD = 46; // visitInsn -从数组加载int到栈顶
int LALOAD = 47; // -从数组加载long到栈顶
int FALOAD = 48; // -从数组加载float到栈顶
int DALOAD = 49; // -从数组加载double到栈顶
int AALOAD = 50; // -从数组加载Object引用到栈顶
int BALOAD = 51; // -从数组加载boolean值到栈顶
int CALOAD = 52; // -从数组加载char值到栈顶
int SALOAD = 53; // -从数组加载short到栈顶
int ISTORE = 54; // visitVarInsn 将int值保存到局部变量表
int LSTORE = 55; // -将long值保存到局部变量表
int FSTORE = 56; // -将float值保存到局部变量表
int DSTORE = 57; // -将double值保存到局部变量表
int ASTORE = 58; // -将Object引用保存到局部变量表
int IASTORE = 79; // visitInsn -将int值保存到数组中
int LASTORE = 80; // -将long值保存到数组中
int FASTORE = 81; // -将float值保存到数组中
int DASTORE = 82; // -将double值保存到数组中
int AASTORE = 83; // -将Object引用保存到数组中
int BASTORE = 84; // -将boolean值保存到数组中
int CASTORE = 85; // -将char值保存到数组中
int SASTORE = 86; // -将short值保存到数组中
int POP = 87; // -丢弃栈顶元素
int POP2 = 88; // -丢弃栈顶的两个元素(如果是double或long就只有一个)
int DUP = 89; // -复制栈顶元素
int DUP_X1 = 90; // -复制栈顶元素,并将其插入栈顶的两个元素下面,形如value2, value1 → value1, value2, value1
int DUP_X2 = 91; // -复制栈顶元素,并将其插入栈顶的三个元素(前提是value2不能是double或long)或两个元素(这时value2是long或double,或占了value
3的位置,形如value3, value2, value1 → value1, value3, value2, value1
int DUP2 = 92; // -复制栈顶的两个元素
int DUP2_X1 = 93; // -形如value3, {value2, value1} → {value2, value1}, value3, {value2, value1}
int DUP2_X2 = 94; // -形如{value4, value3}, {value2, value1} → {value2, value1}, {value4, value3}, {value2, value1}
int SWAP = 95; // -交换栈顶的两个值,注意两个值不能是double或long
int IADD = 96; // -
int LADD = 97; // -
int FADD = 98; // -
int DADD = 99; // -
int ISUB = 100; // -
int LSUB = 101; // -
int FSUB = 102; // -
int DSUB = 103; // -
int IMUL = 104; // -
int LMUL = 105; // -
int FMUL = 106; // -
int DMUL = 107; // -
int IDIV = 108; // -
int LDIV = 109; // -
int FDIV = 110; // -
int DDIV = 111; // -
int IREM = 112; // -
int LREM = 113; // -
int FREM = 114; // -
int DREM = 115; // -
int INEG = 116; // -
int LNEG = 117; // -
int FNEG = 118; // -
int DNEG = 119; // -
int ISHL = 120; // -
int LSHL = 121; // -
int ISHR = 122; // -
int LSHR = 123; // -
int IUSHR = 124; // -
int LUSHR = 125; // -
int IAND = 126; // -
int LAND = 127; // -
int IOR = 128; // -
int LOR = 129; // -
int IXOR = 130; // -
int LXOR = 131; // -
int IINC = 132; // visitIincInsn
int I2L = 133; // visitInsn,将int转为long,以下类推
int I2F = 134; // -
int I2D = 135; // -
int L2I = 136; // -
int L2F = 137; // -
int L2D = 138; // -
int F2I = 139; // -
int F2L = 140; // -
int F2D = 141; // -
int D2I = 142; // -
int D2L = 143; // -
int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
int LCMP = 148; // -比较大小,如果value1>value2将1推到栈顶,相等则是0,反之则为-1
int FCMPL = 149; // -比较两个float,下同
int FCMPG = 150; // -
int DCMPL = 151; // -比较两个double,下同
int DCMPG = 152; // -
int IFEQ = 153; // visitJumpInsn,当栈顶int型数值等于0时跳转
int IFNE = 154; // -当栈顶int型数值不等于0时跳转
int IFLT = 155; // -当栈顶int型数值小于0时跳转
int IFGE = 156; // -当栈顶int型数值大于等于0时跳转
int IFGT = 157; // -当栈顶int型数值大于0时跳转
int IFLE = 158; // -当栈顶int型数值小于等于0时跳转
int IF_ICMPEQ = 159; // -比较栈顶两int型数值大小,当结果等于0时跳转
int IF_ICMPNE = 160; // -比较栈顶两int型数值大小,当结果不等于0时跳转
int IF_ICMPLT = 161; // -比较栈顶两int型数值大小,当结果小于0时跳转
int IF_ICMPGE = 162; // -比较栈顶两int型数值大小,当结果大于等于0时跳转
int IF_ICMPGT = 163; // -比较栈顶两int型数值大小,当结果大于0时跳转
int IF_ICMPLE = 164; // -比较栈顶两int型数值大小,当结果小于等于0时跳转
int IF_ACMPEQ = 165; // -比较栈顶两Object引用,当结果相等时跳转
int IF_ACMPNE = 166; // -比较栈顶两Object引用,当结果不相等时跳转
int GOTO = 167; //-跳转
int JSR = 168; // -跳转至指定16位栈偏移位置,并将jsr下一条指令地址压入栈顶
int RET = 169; // visitVarInsn,返回至本地变量指定的#index的指令位置(一般与jsr, jsr_w联合使用)
int TABLESWITCH = 170; // visiTableSwitchInsn,用于switch条件跳转,case值连续(可变长度指令)
int LOOKUPSWITCH = 171; // visitLookupSwitch,用于switch条件跳转,case值不连续(可变长度指令)
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -返回void
int GETSTATIC = 178; // visitFieldInsn,获取指定类的静态字段,并将其值推到栈顶
int PUTSTATIC = 179; // -为指定类的静态字段赋值
int GETFIELD = 180; // -获取指定类的实例字段,并将其值推到栈顶
int PUTFIELD = 181; // -为指定的类的实例字段赋值
int INVOKEVIRTUAL = 182; // visitMethodInsn,调用实例方法(Java中所有的方法都是可以直接覆写的虚方法,所以叫virtual)
int INVOKESPECIAL = 183; // -调用超类构造方法,实例初始化方法,私有方法
int INVOKESTATIC = 184; // -调用静态方法
int INVOKEINTERFACE = 185; // -调用接口方法
int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn 调用动态方法
int NEW = 187; // visitTypeInsn 创建对象
int NEWARRAY = 188; // visitIntInsn 创建基本类型数组
int ANEWARRAY = 189; // visitTypeInsn 创建对象数组
int ARRAYLENGTH = 190; // visitInsn 将数组长度推入栈顶
int ATHROW = 191; // -将栈顶的异常抛出
int CHECKCAST = 192; // visitTypeInsn 检验类型转换,检验未通过将抛出ClassCastException
int INSTANCEOF = 193; // -检验对象是否是指定的类的实例,如果是将1推入栈顶,否则将0推入栈顶
int MONITORENTER = 194; // visitInsn 获得对象的锁
int MONITOREXIT = 195; // -释放对象锁
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn 如果栈顶元素null时跳转
int IFNONNULL = 199; // -栈顶元素不为null时跳转
}
Last updated