一凡
I love java share!
Toggle navigation
一凡
Home
About Me
Archives
Tags
03 - JVM Class 字节码指令
2019-11-26 09:00:29
295
0
0
qwfylwc
# 字节码指令类型 ## load 是将本地变量中的数据推送入栈中 iload,iload_,lload,lload_,fload,fload_,dload,dload_,aload,aload_ iload_0:将第一个int型本地变量推送至栈顶 iload中i表示为int型(l为long,f为float,d为double ,a为引用类型),load表示动作为load, 后面的指令大多都是这种结构,先是声明操作数类型,再说明具体动作。 同理 fload:将本地变量的float型数据推送栈顶 ## store load是从本地变量到栈顶,store是从栈顶到本地变量 istore,istore_,lstore,lstore_,fstore,fstore_,dstore,dstor_,astore,astore_ istore:将栈顶int型数值存入制定数组的指定索引位置 ## push,const 除了本地变量到栈顶,还有常量到栈顶 bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_ ldc:将int,float或String型常量从常量池中推送至栈顶 iconst_0:将int型0推送至栈顶 ## 算数操作 加:iadd,ladd,fadd,dadd :将栈顶两个数值相加并将将结果压入栈顶 减:is ,ls ,fs ,ds 乘:imul,lmul,fmul,dmul 除:idiv,ldiv,fdiv,ddiv 余数:irem,lrem,frem,drem 取负:ineg,lneg,fneg,dneg 移位:ishl,lshr,iushr,lshl,lshr,lushr 按位或:ior,lor 按位与:iand,land 按位异或:ixor,lxor 类型转换:i2l,i2f,i2d,l2f,l2d,f2d(放宽数值转换) i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f(缩窄数值转换) ## 比较操作 lcmp:比较栈顶两个long型数值的大小,并将结果(1,0,-1)压入栈顶 fcmpl:比较栈顶两个float型数值的大小,并将结果(1,0,-1)压入栈顶,当其中一个为NaN,将-1压入栈顶 fcmpg:......其中一个为NaN,将1压入栈顶 dcmpl dcmpg ## 跳转 ifeq:当栈顶int型数值等于0时跳转 ifne:当栈顶int型数值不等于0时跳转 iflt:当栈顶int型数值小于0时跳转 ifge:大于等于0 ifgt:大于0 ifle:小于等于0 if_icmpeq:比较栈顶两个int大小,等于0跳转 if_icmpne:不等于0跳转 ..... goto:无条件跳转 goto,goto_w,jsr,jsr_w,ret ifnull:为null时跳转 ifnonnull:不为null时跳转 finally关键字的实现使用:jsr,jsr_w,ret ## 返回操作 ireturn:从当前方法返回int lreturn:从当前方法放回long ...... return:从当前方法返回void ## Class的相关操作 getstatic:获取指定类的静态域,并将其值压入栈顶 putstatic:为指定的类的静态域赋值 getfield:获取指定类的实例域,并将其值压入栈顶 pufield:为指定类的实例域赋值 invokevirtual:调用实例方法 invokespecial:调用超类构造方法,实例初始化方法没有方法 invokestatic:调用静态方法 invokeinterface:调用接口方法 invokedynamic:调用动态方法 new:创建一个对象 newarray:创建一个指定的原始类型数组 anewarray:创建一个引用型的数组,并将其引用值压入栈顶 arraylength:获取数组的长度并压入栈顶 athrow:将栈顶的异常抛出 checkcast:检查类型转换,检查未通过会抛出ClassCastException instanceof:检查是否是指定的类的实例,如果是,将1压入栈顶,不是将0压入栈顶 monitorenter:获取对象的锁,用于同步方法或者同步块 monitorexit:释放对象的锁 wide:扩展本地变量的宽度 # 样例详解 ```java class HelloWorld { public int add(int a,int b){ int c = a + b; return c; } } ``` ```shell javac -g HelloWorld.java javap -v -c -l HelloWorld Classfile /D:/HelloWorld.class Last modified 2019-11-26; size 256 bytes MD5 checksum 988a43c6b9af7e702b8de91ed58e77f1 Compiled from "HelloWorld.java" class HelloWorld minor version: 0 major version: 52 flags: ACC_SUPER Constant pool: #1 = Methodref #3.#12 // java/lang/Object."<init>":()V #2 = Class #13 // HelloWorld #3 = Class #14 // java/lang/Object #4 = Utf8 <init> #5 = Utf8 ()V #6 = Utf8 Code #7 = Utf8 LineNumberTable #8 = Utf8 add #9 = Utf8 (II)I #10 = Utf8 SourceFile #11 = Utf8 HelloWorld.java #12 = NameAndType #4:#5 // "<init>":()V #13 = Utf8 HelloWorld #14 = Utf8 java/lang/Object { HelloWorld(); descriptor: ()V flags: Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public int add(int, int); descriptor: (II)I flags: ACC_PUBLIC Code: stack=2, locals=4, args_size=3 0: iload_1 //将a压栈 1: iload_2 //将b压栈 2: iadd //计算a+b并将结果压栈顶 3: istore_3 //从栈顶取值赋给本地变量c 4: iload_3 //将c压栈 5: ireturn //方法返回 LineNumberTable: line 4: 0 line 5: 4 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this LHelloWorld; 0 6 1 a I 0 6 2 b I 4 2 3 c I } SourceFile: "HelloWorld.java" ``` 再看下面这段 ```java class HelloWorld { public int count(){ int i=0; try{ i=1; return i; }finally{ i=2; } } } ``` ```shell public int count(); descriptor: ()I flags: ACC_PUBLIC Code: stack=1, locals=4, args_size=1 0: iconst_0 //将常量0压入栈顶 1: istore_1 //从栈顶取值赋给本地变量1(i=0) 2: iconst_1 //将常量1压入栈顶 3: istore_1 //从栈顶取值赋给本地变量1(i=1) 4: iload_1 //将本地变量1(i=1)压栈 5: istore_2 //从栈顶取值赋给本地变量2(假设为m=1) 6: iconst_2 //将常量2压入栈顶 7: istore_1 //从栈顶取值赋给本地变量1(i=2) 8: iload_2 //将本地变量2(m=1)压栈 9: ireturn //返回 10: astore_3 //从栈顶取值赋给本地变量3(假设为n=1)并出栈 11: iconst_2 //将常量2压入栈顶 12: istore_1 //从栈顶取值赋给本地变量1(i=2) 13: aload_3 //将本地变量3(n=1)压栈 14: athrow Exception table: from to target type 2 6 10 any LineNumberTable: line 4: 0 line 6: 2 line 7: 4 line 9: 6 line 7: 8 line 9: 10 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this LHelloWorld; 2 13 1 i I StackMapTable: number_of_entries = 1 frame_type = 255 /* full_frame */ offset_delta = 10 locals = [ class HelloWorld, int ] stack = [ class java/lang/Throwable ] ``` ``` class HelloWorld { public int count(){ int i=0; try{ i=1; }finally{ i=2; } return i; } } public int count(); descriptor: ()I flags: ACC_PUBLIC Code: stack=1, locals=3, args_size=1 0: iconst_0 //将常量0压入栈顶 1: istore_1 //从栈顶取值赋给本地变量1(i=0) 2: iconst_1 //将常量1压入栈顶 3: istore_1 //从栈顶取值赋给本地变量1(i=1) 4: iconst_2 //将常量2压入栈顶 5: istore_1 //从栈顶取值赋给本地变量1(i=2) 6: goto 14 9: astore_2 //从栈顶取值赋给本地变量2(假设为m=2)并出栈 10: iconst_2 //将常量2压入栈顶 11: istore_1 //从栈顶取值赋给本地变量1(i=2) 12: aload_2 //将本地变量2(m=2)压栈 13: athrow 14: iload_1 //将本地变量1(i=2)压栈 15: ireturn //返回 Exception table: from to target type 2 4 9 any LineNumberTable: line 4: 0 line 6: 2 line 8: 4 line 9: 6 line 8: 9 line 10: 14 StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 9 locals = [ class HelloWorld, int ] stack = [ class java/lang/Throwable ] frame_type = 4 /* same */ ```
Pre:
02 - JVM Class 类结构
Next: No Post
Table of content