JAVA字节码文件分析

JAVA字节码文件分析

案例1 HelloByteCode

源代码

HelloByteCode.java

package com.xianyanyang.jvm.bytecode;
public class HelloByteCode {
    public static void main(String[] args) {
        HelloByteCode obj = new HelloByteCode();
    }
}

字节码文件

执行以下java命令生成字节码文件HelloByteCode.class:

javac -g HelloByteCode.java
cafe babe 0000 0034 0016 0a00 0400 1307
0014 0a00 0200 1307 0015 0100 063c 696e
6974 3e01 0003 2829 5601 0004 436f 6465
0100 0f4c 696e 654e 756d 6265 7254 6162
6c65 0100 124c 6f63 616c 5661 7269 6162
6c65 5461 626c 6501 0004 7468 6973 0100
2c4c 636f 6d2f 7869 616e 7961 6e79 616e
672f 6a76 6d2f 6279 7465 636f 6465 2f48
656c 6c6f 4279 7465 436f 6465 3b01 0004
6d61 696e 0100 1628 5b4c 6a61 7661 2f6c
616e 672f 5374 7269 6e67 3b29 5601 0004
6172 6773 0100 135b 4c6a 6176 612f 6c61
6e67 2f53 7472 696e 673b 0100 036f 626a
0100 0a53 6f75 7263 6546 696c 6501 0012
4865 6c6c 6f42 7974 6543 6f64 652e 6a61
7661 0c00 0500 0601 002a 636f 6d2f 7869
616e 7961 6e79 616e 672f 6a76 6d2f 6279
7465 636f 6465 2f48 656c 6c6f 4279 7465
436f 6465 0100 106a 6176 612f 6c61 6e67
2f4f 626a 6563 7400 2100 0200 0400 0000
0000 0200 0100 0500 0600 0100 0700 0000
2f00 0100 0100 0000 052a b700 01b1 0000
0002 0008 0000 0006 0001 0000 0003 0009
0000 000c 0001 0000 0005 000a 000b 0000
0009 000c 000d 0001 0007 0000 0041 0002
0002 0000 0009 bb00 0259 b700 034c b100
0000 0200 0800 0000 0a00 0200 0000 0600
0800 0700 0900 0000 1600 0200 0000 0900
0e00 0f00 0000 0800 0100 1000 0b00 0100
0100 1100 0000 0200 12

文件开头的4个字节"cafe babe"称之为魔数,只有以"cafe babe"开头的class文件才可以被JVM接受,这四个字节就是字节码文件的身份识别。

字节码文件内容为十六进制;一个操作码为1Byte=8bit,一个十六进制数字=4个bit=(1/2) Byte,一个操作码=2个十六进制数 ,如上图红色标记 bb为一个操作码,映射指令为 new;

字节码注记符文件

javap -c -verbose HelloByteCode.class > HelloByteCode.txt
Classfile /E:/.../week1/src/main/java/com/xianyanyang/jvm/bytecode/HelloByteCode.class
  Last modified 2021-3-2; size 473 bytes
  MD5 checksum f136062421deb48ad26d540039f82d47
  Compiled from "HelloByteCode.java"
public class com.xianyanyang.jvm.bytecode.HelloByteCode
  minor version: 0    --- 次版本号
  major version: 52   --- 主版本号,52即java 8 ,51对应java 7
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
--- Constant pool,常量池可以理解为Class中的资源仓库。
--- 主要存放两大常量:
--- 1)字面量,类似于Java中的常量概念,包括文本字符串,final常量等。
--- 2)符号引用,包括:类和接口的全限定名、字段的名称和描述符号、方法的名称和描述符

   #1 = Methodref          #4.#19         // java/lang/Object."<init>":()V
--- 第一个常量是一个方法定义,指向了第4个和第13个常量。
    --- 由此类推查看第4个和第13个常量,最后拼接成一个常量右侧的注释内容:“java/lang/Object."<init>":()V”
    --- 这段可以理解为该类的构造器声明,由于该类没有重写构造说明,所以调用的是父类的构造方法。
    --- 此处说明该类的父类是Object,该方法的默认返回值是V,也就是void,无返回值。

   #2 = Class              #20            // com/xianyanyang/jvm/bytecode/HelloByteCode
   #3 = Methodref          #2.#19         // com/xianyanyang/jvm/bytecode/HelloByteCode."<init>":()V
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               LocalVariableTable
  #10 = Utf8               this
  #11 = Utf8               Lcom/xianyanyang/jvm/bytecode/HelloByteCode;
  #12 = Utf8               main
  #13 = Utf8               ([Ljava/lang/String;)V
  #14 = Utf8               args
  #15 = Utf8               [Ljava/lang/String;
  #16 = Utf8               obj
  #17 = Utf8               SourceFile
  #18 = Utf8               HelloByteCode.java
  #19 = NameAndType        #5:#6          // "<init>":()V
  #20 = Utf8               com/xianyanyang/jvm/bytecode/HelloByteCode
  #21 = Utf8               java/lang/Object
{
  --- 构造函数
  public com.xianyanyang.jvm.bytecode.HelloByteCode();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0           --- 将第一个引用类型本地变量压栈
         1: invokespecial #1  // Method java/lang/Object."<init>":()V ---调用(#1)Object构造方法,实例初始化方法
         4: return            --- 从当前方法返回void
      
      LineNumberTable: --- 存放方法的行号信息。
      --- 源代码行数:字节码行数 
        line 3: 0
        
      LocalVariableTable: --- 方法本地变量表,描述了栈帧中局部变量的信息。
      --- Start表示该局部变量在哪一行开始可见;
          Length表示可见行数,也就是该变量的作用范围;
          Slot代表所在栈帧位置;
          Name是变量名称;
          Signature是类型签名;
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/xianyanyang/jvm/bytecode/HelloByteCode;
            
  --- main函数
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2   // class com/xianyanyang/jvm/bytecode/HelloByteCode --- new HelloByteCode ()
         3: dup                -- 复制栈顶数值并将复制值压入栈顶
         4: invokespecial #3   // Method "<init>":()V   --- 调用(#3)HelloByteCode构造方法,实例初始化方法
         7: astore_1           -- 将栈顶引用型数值存入本地变量orj
         8: return             -- 从当前方法返回void
      LineNumberTable:
        line 6: 0
        line 7: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
            8       1     1   obj   Lcom/xianyanyang/jvm/bytecode/HelloByteCode;
}
SourceFile: "HelloByteCode.java"

案例2 四则运算类Math

源代码

package com.xianyanyang.jvm.bytecode;

public class Math {

    public void foo() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 5;
    }
}

字节码注记符文件

Classfile /E:/JAVA-01/...week1/src/main/java/com/xianyanyang/jvm/bytecode/Math.class
  Last modified 2021-3-2; size 426 bytes
  MD5 checksum 44f9ad9392429e85ad1895169810dbad
  Compiled from "Math.java"
public class com.xianyanyang.jvm.bytecode.Math
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#18         // java/lang/Object."<init>":()V
   #2 = Class              #19            // com/xianyanyang/jvm/bytecode/Math
   #3 = Class              #20            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               Lcom/xianyanyang/jvm/bytecode/Math;
  #11 = Utf8               foo
  #12 = Utf8               a
  #13 = Utf8               I
  #14 = Utf8               b
  #15 = Utf8               c
  #16 = Utf8               SourceFile
  #17 = Utf8               Math.java
  #18 = NameAndType        #4:#5          // "<init>":()V
  #19 = Utf8               com/xianyanyang/jvm/bytecode/Math
  #20 = Utf8               java/lang/Object
{
  public com.xianyanyang.jvm.bytecode.Math();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/xianyanyang/jvm/bytecode/Math;

  --  public void foo() {
  --      int a = 1;
  --      int b = 2;
  --      int c = (a + b) * 5;
  --  }
    
  public void foo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: iconst_1   --  将int型1压栈
         1: istore_1   --  将栈顶int型数值存入本地变量 a
         2: iconst_2   --  将int型2压栈
         3: istore_2   --  将栈顶int型数值存入本地变量 b
         4: iload_1    --  将int型本地变量 a 压栈
         5: iload_2    --  将int型本地变量 b 压栈
         6: iadd       --  将栈顶a和b两int型数值相加并将结果压栈
         7: iconst_5   --  将int型5压栈
         8: imul       --  将栈顶两int型数值相乘并将结果压入栈顶
         9: istore_3   --  将栈顶int型数值存入本地变量c
        10: return     --  从当前方法返回void
      LineNumberTable:
        line 6: 0
        line 7: 2
        line 8: 4
        line 9: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Lcom/xianyanyang/jvm/bytecode/Math;
            2       9     1     a   I
            4       7     2     b   I
           10       1     3     c   I
}
SourceFile: "Math.java"

案例三 循环Loop

源代码

package com.xianyanyang.jvm.bytecode;

public class Loop {
    private int result = 0;

    public void loop(int[] numbers) {
        for (int number : numbers) {
            result += number;
        }
    }
}

编译后的文件

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.xianyanyang.jvm.bytecode;

public class Loop {
    private int result = 0;

    public Loop() {
    }

    public void loop(int[] ages) {
        int[] var2 = ages;
        int var3 = ages.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            int age = var2[var4];
            this.result += age;
        }
    }
}

字节码注记符文件

Classfile /E:/JAVA-01/Week_01/2021-02-28/week1/src/main/java/com/xianyanyang/jvm/bytecode/Loop.class
  Last modified 2021-3-2; size 532 bytes
  MD5 checksum 669ecc2bf8a1e49062a3eed1b3b1fb04
  Compiled from "Loop.java"
public class com.xianyanyang.jvm.bytecode.Loop
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#23         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#24         // com/xianyanyang/jvm/bytecode/Loop.result:I
   #3 = Class              #25            // com/xianyanyang/jvm/bytecode/Loop
   #4 = Class              #26            // java/lang/Object
   #5 = Utf8               result
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/xianyanyang/jvm/bytecode/Loop;
  #14 = Utf8               loop
  #15 = Utf8               ([I)V
  #16 = Utf8               age
  #17 = Utf8               ages
  #18 = Utf8               [I
  #19 = Utf8               StackMapTable
  #20 = Class              #18            // "[I"
  #21 = Utf8               SourceFile
  #22 = Utf8               Loop.java
  #23 = NameAndType        #7:#8          // "<init>":()V
  #24 = NameAndType        #5:#6          // result:I
  #25 = Utf8               com/xianyanyang/jvm/bytecode/Loop
  #26 = Utf8               java/lang/Object
{
  public com.xianyanyang.jvm.bytecode.Loop();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_0
         6: putfield      #2                  // Field result:I
         9: return
      LineNumberTable:
        line 3: 0
        line 4: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/xianyanyang/jvm/bytecode/Loop;

    -- public void loop(int[] ages) {
    --    int[] var2 = ages;
    --    int var3 = ages.length;
    --    for(int var4 = 0; var4 < var3; ++var4) {
    --        int age = var2[var4];
    --        this.result += age;
    --    }
    -- }
  public void loop(int[]);
    descriptor: ([I)V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=6, args_size=2
         0: aload_1         	-- 将Slot1引用类型本地变量推送至栈顶 ages 
         1: astore_2         	-- 将栈顶引用型数值存入Slot2本地变量 var2
         2: aload_2         	-- 将Slot2引用类型本地变量推送至栈顶 var2
         3: arraylength         -- 将数组从栈中弹出,获得数组的长度值并压入栈顶 var2.length
         4: istore_3         	-- 将栈顶int型数值存入Slot3本地变量 var3
         5: iconst_0         	-- 将int型0推送至栈顶
         6: istore        4         -- 将栈顶int型数值存入指定本地变量 var4
         8: iload         4         -- 将指定的int型本地变量推送至栈顶 var4
        10: iload_3         		-- 将Slot3的int型本地变量推送至栈顶 var3
        11: if_icmpge     37        -- 比较栈顶两int型数值var4和var3的大小,当结果大于等于0时跳转
        14: aload_2         		-- 将Slot2引用类型本地变量推送至栈顶 var2
        15: iload         4         -- 将指定的int型本地变量推送至栈顶 var4
        17: iaload         			-- 将int型数组指定索引的值推送至栈顶 var2[var4]
        18: istore        5         -- 将栈顶int型数值存入指定本地变量 age
        20: aload_0         		-- 将Slot0的引用类型本地变量推送至栈顶 this
        21: dup         			-- 复制栈顶数值并将复制值压入栈顶 this
        22: getfield      #2        -- 获取指定类的实例域,并将其值压入栈顶 this.result    // Field result:I
        25: iload         5         -- 将指定的int型本地变量推送至栈顶 age
        27: iadd         			-- 将栈顶两int型数值相加并将结果压入栈顶 this.result+age
        28: putfield      #2        -- 为指定的类的实例域赋值 		this.result			// Field result:I
        31: iinc          4, 1      -- 将指定int型变量增加指定值   var4+1
        34: goto          8         -- 无条件跳转
        37: return         			-- 从当前方法返回void
      LineNumberTable:
        line 7: 0
        line 8: 20
        line 7: 31
        line 10: 37
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           20      11     5   age   I
            0      38     0  this   Lcom/xianyanyang/jvm/bytecode/Loop;
            0      38     1  ages   [I
                        --2  var2
                        --3  var3
                        --4  var4
      StackMapTable: number_of_entries = 2
        frame_type = 254 /* append */
          offset_delta = 8
          locals = [ class "[I", int, int ]
        frame_type = 248 /* chop */
          offset_delta = 28
}
SourceFile: "Loop.java"

Constant Pool常量池定义列表

CONSTANT_Class_info描述
utf8UTF-8编码的字符串
integer整型字面量
Float浮点数字面量
Long长整型字面量
Double双精度浮点型字面量
Class类或者接口的符号引用
String字符串类型字面量
Fieldref字段的符号引用
Methodref类中方法的符号引用
InterfaceMethodref接口中方法的符号引用
NameAndType字段或方法的符号引用
MethodType标志方法类型
MethodHandle表示方法句柄
InvokeDynamic表示一个动态方法调用点

字面量又称为直接量,是指在程序中通过源代码直接给出的值,例如在int a = 5;代码中,为变量 a 所分配的初始值 5 就是一个直字面量。

常用的JAVA字节码指令码注记符对应表

指令码注记符说明
0x00nop什么都不做
0x01aconst_null将null压栈
0x02iconst_m1将int型-1压栈
0x03iconst_0将int型0压栈
0x04iconst_1将int型1压栈
0x05iconst_2将int型2压栈
0x06iconst_3将int型3压栈
0x07iconst_4将int型4压栈
0x08iconst_5将int型5压栈
0x09lconst_0将long型0压栈
0x0alconst_1将long型1压栈
0x0bfconst_0将float型0压栈
0x0cfconst_1将float型1压栈
0x0dfconst_2将float型2压栈
0x0edconst_0将double型0压栈
0x0fdconst_1将double型1压栈
0x10bipush将单字节的常量值(-128~127)压栈
0x11sipush将一个短整型常量值(-32768~32767)压栈
0x12ldc将int, float或String型常量值从常量池中压栈
0x13ldc_w将int, float或String型常量值从常量池中压栈(宽索引)
0x14ldc2_w将long或double型常量值从常量池中压栈(宽索引)
0x15iload将指定的int型本地变量压栈
0x16lload将指定的long型本地变量压栈
0x17fload将指定的float型本地变量压栈
0x18dload将指定的double型本地变量压栈
0x19aload将指定的引用类型本地变量压栈
0x1aiload_0将第一个int型本地变量压栈
0x1biload_1将第2个int型本地变量压栈
0x1ciload_2将第三个int型本地变量压栈
0x1diload_3将第四个int型本地变量压栈
0x1elload_0将第一个long型本地变量压栈
0x1flload_1将第2个long型本地变量压栈
0x20lload_2将第三个long型本地变量压栈
0x21lload_3将第四个long型本地变量压栈
0x22fload_0将第一个float型本地变量压栈
0x23fload_1将第2个float型本地变量压栈
0x24fload_2将第三个float型本地变量压栈
0x25fload_3将第四个float型本地变量压栈
0x26dload_0将第一个double型本地变量压栈
0x27dload_1将第2个double型本地变量压栈
0x28dload_2将第三个double型本地变量压栈
0x29dload_3将第四个double型本地变量压栈
0x2aaload_0将第一个引用类型本地变量压栈
0x2baload_1将第2个引用类型本地变量压栈
0x2caload_2将第三个引用类型本地变量压栈
0x2daload_3将第四个引用类型本地变量压栈
0x2eiaload将int型数组指定索引的值压栈
0x2flaload将long型数组指定索引的值压栈
0x30faload将float型数组指定索引的值压栈
0x31daload将double型数组指定索引的值压栈
0x32aaload将引用型数组指定索引的值压栈
0x33baload将boolean或byte型数组指定索引的值压栈
0x34caload将char型数组指定索引的值压栈
0x35saload将short型数组指定索引的值压栈
0x36istore将栈顶int型数值存入指定本地变量
0x37lstore将栈顶long型数值存入指定本地变量
0x38fstore将栈顶float型数值存入指定本地变量
0x39dstore将栈顶double型数值存入指定本地变量
0x3aastore将栈顶引用型数值存入指定本地变量
0x3bistore_0将栈顶int型数值存入第一个本地变量
0x3cistore_1将栈顶int型数值存入第2个本地变量
0x3distore_2将栈顶int型数值存入第三个本地变量
0x3eistore_3将栈顶int型数值存入第四个本地变量
0x3flstore_0将栈顶long型数值存入第一个本地变量
0x40lstore_1将栈顶long型数值存入第2个本地变量
0x41lstore_2将栈顶long型数值存入第三个本地变量
0x42lstore_3将栈顶long型数值存入第四个本地变量
0x43fstore_0将栈顶float型数值存入第一个本地变量
0x44fstore_1将栈顶float型数值存入第2个本地变量
0x45fstore_2将栈顶float型数值存入第三个本地变量
0x46fstore_3将栈顶float型数值存入第四个本地变量
0x47dstore_0将栈顶double型数值存入第一个本地变量
0x48dstore_1将栈顶double型数值存入第2个本地变量
0x49dstore_2将栈顶double型数值存入第三个本地变量
0x4adstore_3将栈顶double型数值存入第四个本地变量
0x4bastore_0将栈顶引用型数值存入第一个本地变量
0x4castore_1将栈顶引用型数值存入第2个本地变量
0x4dastore_2将栈顶引用型数值存入第三个本地变量
0x4eastore_3将栈顶引用型数值存入第四个本地变量
0x4fiastore将栈顶int型数值存入指定数组的指定索引位置
0x50lastore将栈顶long型数值存入指定数组的指定索引位置
0x51fastore将栈顶float型数值存入指定数组的指定索引位置
0x52dastore将栈顶double型数值存入指定数组的指定索引位置
0x53aastore将栈顶引用型数值存入指定数组的指定索引位置
0x54bastore将栈顶boolean或byte型数值存入指定数组的指定索引位置
0x55castore将栈顶char型数值存入指定数组的指定索引位置
0x56sastore将栈顶short型数值存入指定数组的指定索引位置
0x57pop将栈顶数值弹出 (数值不能是long或double类型的)
0x58pop2将栈顶的一个(long或double类型的)或两个数值弹出(其它)
0x59dup复制栈顶数值并将复制值压入栈顶
0x5adup_x1复制栈顶数值并将两个复制值压入栈顶
0x5bdup_x2复制栈顶数值并将三个(或两个)复制值压入栈顶
0x5cdup2复制栈顶一个(long或double类型的)或两个(其它)数值并将复制值压入栈顶
0x5ddup2_x1<待补充>
0x5edup2_x2<待补充>
0x5fswap将栈最顶端的两个数值互换(数值不能是long或double类型的)
0x60iadd将栈顶两int型数值相加并将结果压入栈顶
0x61ladd将栈顶两long型数值相加并将结果压入栈顶
0x62fadd将栈顶两float型数值相加并将结果压入栈顶
0x63dadd将栈顶两double型数值相加并将结果压入栈顶
0x64isub将栈顶两int型数值相减并将结果压入栈顶
0x65lsub将栈顶两long型数值相减并将结果压入栈顶
0x66fsub将栈顶两float型数值相减并将结果压入栈顶
0x67dsub将栈顶两double型数值相减并将结果压入栈顶
0x68imul将栈顶两int型数值相乘并将结果压入栈顶
0x69lmul将栈顶两long型数值相乘并将结果压入栈顶
0x6afmul将栈顶两float型数值相乘并将结果压入栈顶
0x6bdmul将栈顶两double型数值相乘并将结果压入栈顶
0x6cidiv将栈顶两int型数值相除并将结果压入栈顶
0x6dldiv将栈顶两long型数值相除并将结果压入栈顶
0x6efdiv将栈顶两float型数值相除并将结果压入栈顶
0x6fddiv将栈顶两double型数值相除并将结果压入栈顶
0x70irem将栈顶两int型数值作取模运算并将结果压入栈顶
0x71lrem将栈顶两long型数值作取模运算并将结果压入栈顶
0x72frem将栈顶两float型数值作取模运算并将结果压入栈顶
0x73drem将栈顶两double型数值作取模运算并将结果压入栈顶
0x74ineg将栈顶int型数值取负并将结果压入栈顶
0x75lneg将栈顶long型数值取负并将结果压入栈顶
0x76fneg将栈顶float型数值取负并将结果压入栈顶
0x77dneg将栈顶double型数值取负并将结果压入栈顶
0x78ishl将int型数值左移位指定位数并将结果压入栈顶
0x79lshl将long型数值左移位指定位数并将结果压入栈顶
0x7aishr将int型数值右(符号)移位指定位数并将结果压入栈顶
0x7blshr将long型数值右(符号)移位指定位数并将结果压入栈顶
0x7ciushr将int型数值右(无符号)移位指定位数并将结果压入栈顶
0x7dlushr将long型数值右(无符号)移位指定位数并将结果压入栈顶
0x7eiand将栈顶两int型数值作“按位与”并将结果压入栈顶
0x7fland将栈顶两long型数值作“按位与”并将结果压入栈顶
0x80ior将栈顶两int型数值作“按位或”并将结果压入栈顶
0x81lor将栈顶两long型数值作“按位或”并将结果压入栈顶
0x82ixor将栈顶两int型数值作“按位异或”并将结果压入栈顶
0x83lxor将栈顶两long型数值作“按位异或”并将结果压入栈顶
0x84iinc将指定int型变量增加指定值(i++, i–, i+=2)
0x85i2l将栈顶int型数值强制转换成long型数值并将结果压入栈顶
0x86i2f将栈顶int型数值强制转换成float型数值并将结果压入栈顶
0x87i2d将栈顶int型数值强制转换成double型数值并将结果压入栈顶
0x88l2i将栈顶long型数值强制转换成int型数值并将结果压入栈顶
0x89l2f将栈顶long型数值强制转换成float型数值并将结果压入栈顶
0x8al2d将栈顶long型数值强制转换成double型数值并将结果压入栈顶
0x8bf2i将栈顶float型数值强制转换成int型数值并将结果压入栈顶
0x8cf2l将栈顶float型数值强制转换成long型数值并将结果压入栈顶
0x8df2d将栈顶float型数值强制转换成double型数值并将结果压入栈顶
0x8ed2i将栈顶double型数值强制转换成int型数值并将结果压入栈顶
0x8fd2l将栈顶double型数值强制转换成long型数值并将结果压入栈顶
0x90d2f将栈顶double型数值强制转换成float型数值并将结果压入栈顶
0x91i2b将栈顶int型数值强制转换成byte型数值并将结果压入栈顶
0x92i2c将栈顶int型数值强制转换成char型数值并将结果压入栈顶
0x93i2s将栈顶int型数值强制转换成short型数值并将结果压入栈顶
0x94lcmp比较栈顶两long型数值大小,并将结果(1,0,-1)压入栈顶
0x95fcmpl比较栈顶两float型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将-1压入栈顶
0x96fcmpg比较栈顶两float型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将1压入栈顶
0x97dcmpl比较栈顶两double型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将-1压入栈顶
0x98dcmpg比较栈顶两double型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将1压入栈顶
0x99ifeq当栈顶int型数值等于0时跳转
0x9aifne当栈顶int型数值不等于0时跳转
0x9biflt当栈顶int型数值小于0时跳转
0x9cifge当栈顶int型数值大于等于0时跳转
0x9difgt当栈顶int型数值大于0时跳转
0x9eifle当栈顶int型数值小于等于0时跳转
0x9fif_icmpeq比较栈顶两int型数值大小,当结果等于0时跳转
0xa0if_icmpne比较栈顶两int型数值大小,当结果不等于0时跳转
0xa1if_icmplt比较栈顶两int型数值大小,当结果小于0时跳转
0xa2if_icmpge比较栈顶两int型数值大小,当结果大于等于0时跳转
0xa3if_icmpgt比较栈顶两int型数值大小,当结果大于0时跳转
0xa4if_icmple比较栈顶两int型数值大小,当结果小于等于0时跳转
0xa5if_acmpeq比较栈顶两引用型数值,当结果相等时跳转
0xa6if_acmpne比较栈顶两引用型数值,当结果不相等时跳转
0xa7goto无条件跳转
0xa8jsr跳转至指定16位offset位置,并将jsr下一条指令地址压入栈顶
0xa9ret返回至本地变量指定的index的指令位置(一般与jsr, jsr_w联合使用)
0xaatableswitch用于switch条件跳转,case值连续(可变长度指令)
0xablookupswitch用于switch条件跳转,case值不连续(可变长度指令)
0xacireturn从当前方法返回int
0xadlreturn从当前方法返回long
0xaefreturn从当前方法返回float
0xafdreturn从当前方法返回double
0xb0areturn从当前方法返回对象引用
0xb1return从当前方法返回void
0xb2getstatic获取指定类的静态域,并将其值压入栈顶
0xb3putstatic为指定的类的静态域赋值
0xb4getfield获取指定类的实例域,并将其值压入栈顶
0xb5putfield为指定的类的实例域赋值
0xb6invokevirtual调用实例方法
0xb7invokespecial调用超类构造方法,实例初始化方法,私有方法
0xb8invokestatic调用静态方法
0xb9invokeinterface调用接口方法
0xba
0xbbnew创建一个对象,并将其引用值压入栈顶
0xbcnewarray创建一个指定原始类型(如int, float, char…)的数组,并将其引用值压入栈顶
0xbdanewarray创建一个引用型(如类,接口,数组)的数组,并将其引用值压入栈顶
0xbearraylength获得数组的长度值并压入栈顶
0xbfathrow将栈顶的异常抛出
0xc0checkcast检验类型转换,检验未通过将抛出ClassCastException
0xc1instanceof检验对象是否是指定的类的实例,如果是将1压入栈顶,否则将0压入栈顶
0xc2monitorenter获得对象的锁,用于同步方法或同步块
0xc3monitorexit释放对象的锁,用于同步方法或同步块
0xc4wide<待补充>
0xc5multianewarray创建指定类型和指定维度的多维数组(执行该指令时,操作栈中必须包含各维度的长度值),并将其引用值压入栈顶
0xc6ifnull为null时跳转
0xc7ifnonnull不为null时跳转
0xc8goto_w无条件跳转(宽索引)
0xc9jsr_w跳转至指定32位offset位置,并将jsr_w下一条指令地址压入栈顶
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值