數據類型:
class 文件結構
minor version:副版本
major version:主版本號
文件的版本號 major_version.minor_version
flags:訪問標誌
- ACC_PUBLICH 聲明為publich
- ACC_FINAL 聲明為final
- ACC_SUPER 當用到invokespecial指令時,需要對父類方法做特殊處理
- ACC_INTERFACE 該class文件定義的是接口而不是類
- ACC_ABSTRACT 聲明為abstract
- ACC_SYNTHETIC 聲明為synthetic
- ACC_ANNOTATION 標識註解類型
- ACC_ENUM 標識枚舉類型
constant pool 常量池
方法調用和返回指令
- invokevirtual 指令用於調用對象的實例方法,根據對象的實際類型進行分派
- invokeinterface 指令用於調用接口方法,它會在運行時搜索由特定對象實現的這個接口方法,並找出適合的方法進行調用
- invokespecial 指令用於調用一些需要特殊的實例方法,包括實例的初始化,私有方法和父類方法
- invokestatic 指令用於調用命名類中的靜態方法
- invokedynamic 指令用於調用可以綁定invokedynamic指令的調用點對象作為目標方法。
aaload_<n>:從局部變量表中加載索引值為n的引用
aconst_null:將一個null值壓入到操作數棧頂
putfield:為制定類的字段賦值
通過執行javac xxx.java javap -verbose xxx.class 查看class文件
public class AconstNullDemo { Integer i=null; void test{ i=1; if(i.equals(Integer.valueOf(1))){ System.out.println("eq"); } } } public class common.jvm.AconstNullDemo minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #9.#20 // java/lang/Object."<init>":V #2 = Fieldref #8.#21 // common/jvm/AconstNullDemo.i:Ljava/lang/Integer; #3 = Methodref #22.#23 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer; #4 = Methodref #22.#24 // java/lang/Integer.equals:(Ljava/lang/Object;)Z #5 = Fieldref #25.#26 // java/lang/System.out:Ljava/io/PrintStream; #6 = String #27 // eq #7 = Methodref #28.#29 // java/io/PrintStream.println:(Ljava/lang/String;)V #8 = Class #30 // common/jvm/AconstNullDemo #9 = Class #31 // java/lang/Object #10 = Utf8 i #11 = Utf8 Ljava/lang/Integer; #12 = Utf8 <init> #13 = Utf8 V #14 = Utf8 Code #15 = Utf8 LineNumberTable #16 = Utf8 test #17 = Utf8 StackMapTable #18 = Utf8 SourceFile #19 = Utf8 AconstNullDemo.java #20 = NameAndType #12:#13 // "<init>":V #21 = NameAndType #10:#11 // i:Ljava/lang/Integer; #22 = Class #32 // java/lang/Integer #23 = NameAndType #33:#34 // valueOf:(I)Ljava/lang/Integer; #24 = NameAndType #35:#36 // equals:(Ljava/lang/Object;)Z #25 = Class #37 // java/lang/System #26 = NameAndType #38:#39 // out:Ljava/io/PrintStream; #27 = Utf8 eq #28 = Class #40 // java/io/PrintStream #29 = NameAndType #41:#42 // println:(Ljava/lang/String;)V #30 = Utf8 common/jvm/AconstNullDemo #31 = Utf8 java/lang/Object #32 = Utf8 java/lang/Integer #33 = Utf8 valueOf #34 = Utf8 (I)Ljava/lang/Integer; #35 = Utf8 equals #36 = Utf8 (Ljava/lang/Object;)Z #37 = Utf8 java/lang/System #38 = Utf8 out #39 = Utf8 Ljava/io/PrintStream; #40 = Utf8 java/io/PrintStream #41 = Utf8 println #42 = Utf8 (Ljava/lang/String;)V { java.lang.Integer i; descriptor: Ljava/lang/Integer; flags: public common.jvm.AconstNullDemo; 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 //將null壓入棧頂 5: aconst_null //將null賦值給屬性i 6: putfield #2 // Field i:Ljava/lang/Integer; 9: return LineNumberTable: line 6: 0 line 7: 4 void test; descriptor: V flags: Code: stack=2, locals=1, args_size=1 //加載this到操作棧 0: aload_0 //加載常量1到操作棧 1: iconst_1 //調用靜態方法 2: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; //將計算結果賦值給屬性,為什麼putfield的索引不是連續的?這是因為invokestatic操作和操作數長度為3個slot 5: putfield #2 // Field i:Ljava/lang/Integer; //加載this到操作棧 8: aload_0 //將屬性壓入棧頂 9: getfield #2 // Field i:Ljava/lang/Integer; //加載常量1到操作棧頂 12: iconst_1 //調用靜態方法Integer.valueOf 13: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; //調用虛方法equals 16: invokevirtual #4 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z //如果ifeq的結果為0則挑戰到30行 19: ifeq 30 22: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 25: ldc #6 // String eq 27: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 30: return LineNumberTable: line 10: 0 line 11: 8 line 12: 22 line 14: 30 StackMapTable: number_of_entries = 1 frame_type = 30 /* same */ }
相關推薦
推薦中...