JVM-class文件詳解(官方直譯)含腦圖

獲取腦圖方式請看最下面!
在這裏插入圖片描述

JVM

類文件(Class文件)結構

ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

magic u4

  • value:0xCAFEBABE

minor_version u2

  • 0000 暫時不用這兩個字節

major_version u2

  • 0034 表示版本號爲52 表示jdk1.8

constant_pool_count u2

  • value:0025 對應10進制397代表常量池中39個常量

constant_pool[constant_pool_count-1] cp_info 常量池,有tag,info[] info[]的值根據tag的值變化而變化,後面0X…表示tag的值

cp_info {
u1 tag;
u1 info[];
}

  • CONSTANT_Utf8_info u1+u2+u1*length 0x01

    • tag u1:1
    • length u2 bytes中的字節數組長度(不是結果字符串的長度)
    • bytes u1 bytes數組包含字符串的字節。
  • CONSTANT_Integer_info u1+u4 0x03

    • tag u1:3
    • bytes u4 按照高位在前存儲的int值,由ASCII轉換成16進制獲得
  • CONSTANT_float_info u1+u4 0x04

    • tag u1:4
    • bytes u4 按照高位在前存儲的float值,由ASCII轉換成16進制獲得(IEEE 754 floating-point single format)
  • CONSTANT_Long_info u1+u8 0x05

    • tag u1:5
    • high_bytes u4
    • low_bytes u4
  • CONSTANT_Double_info u1+u8 0x06

    • tag u1:6
    • high_bytes u4
    • low_bytes u4
  • CONSTANT_class_info u1+u2 0x07

    • tag u1:7
    • name_index u2 指向權限定名常量池utf8的索引
  • CONSTANT_String_info u1+u2 0x08

    • tag u1:8
    • string_index u2 指向CONSTANT_Utf8_info的索引
  • CONSTANT_Fieldref_info u1+u2+u2 0x09

    • tag u1 :9
    • class_index u2 可以是class類型也可以是接口類型,指向常量池中的有效索引,類型是CONSTANT_Class_info結構
    • name_and_type_index u2 指向字段描述符 CONSTANT_NameAndType_info的索引項(請參考字段描述符)
  • CONSTANT_Methodref_info u1+u2+u2 0x0a

    • tag u1:10
    • class_index u2 必須是class類型,不是接口類型,
    • name_and_type_index u2 指向方法描述符CONSTANT_NameAndType_info的索引項(請參考方法描述符)如果方法名以’<’(’\u003c’)開頭,名字必須是特殊的名字(實例初始化會用到),返回類型必須是void
  • CONSTANT_Interface_Methodref_info u5 0x0b

    • tag u1:11
    • class_index u2 必須是接口類型
    • name_and_type_index u2 指向名稱及類型描述 符CONSTANT_NameAndType_info的索引項
  • CONSTANT_NameAndType_info u5 0x0c

    • tag u1:12

    • name_index u2 指向該字段或方法名稱的CONSTANT_Utf8_info索引

      Class文件中變量,方法的名字以非限定名的形式保存的,簡單講就是單純的變量名或方法名,是不能包含./[;等ASCII字符的。但有個例外

    • descriptor_index u2 指向CONSTANT_Utf8_info結構,代表一個驗證的字段描述符或方法描述符

  • CONSTANT_MethodHandle_info u5 0x0f

    • tag u1 :15

    • reference_kind u2 決定方法類型,值必須是0- 9,該值表示方法句柄的字節碼行爲

    • reference_index u2 值必須是常量池的有效索引

      • 1.reference_kind=1||2||3||4,指向CONSTANT_Fieldref_info索引

      • 2.reference_kind=5||8,指向CONSTANT_Methodref_info索引

      • 3.reference_kind=6||7

        • 類文件版本<52: 指向CONSTANT_Methodref_info索引
        • 類文件版本>=52: 指向CONSTANT_Methodref_info或者CONSTANT_InterfaceMethodref_info索引
      • 4.reference_kind=9,指向CONSTANT_InterfaceMethodref_info索引

      • 5.reference_kind=8,指向CONSTANT_Methodref_info結構必須是方法

  • CONSTANT_MethodType_info u3 0x10

    • tag u1 :16
    • descriptor_index u2 值必須是常量池的有效索 引,常量池在該索引的項必須是CONSTANT_ Utf8_info結構,表示該方法的描述符
  • CONSTANT_InvokeDynamic_info u5 0x12

    • tag u1 :18
    • bootstrap_method_attr_index u2 當前Class文 件中引導方法表的bootstrap_methods[]數組的 有效索引
    • name_and type_index u2 指向名稱及類型描述 符CONSTANT_NameAndType_info的索引項

access_flags u2

  • ACC_PUBLIC 0001可以被包的類訪問
  • ACC_FINAL 0010 不允許有子類
  • ACC_SUPER 0020 當用到invokespecial指令 時,需要特殊處理的父類方法
  • ACC_INTEFACE 0200 標識定義的是接口而不 是類
  • ACC_ABSTRACT 0400 不能被實例化,抽象
  • ACC_ANNOTATION 2000 標識註解類型
  • ACC_ENUM 4000 標識枚舉類型
  • ACC_SYNTHETIC 1000 標識這個類是否是用戶 代碼生成。0表示由用戶代碼生成

this_class u2 :指向一個常量池,一般都指向CONSTANT_class_info類型

super_class u2:指向一個常量池,一般都指向CONSTANT_class_info類型

interfaces_count u2:記錄接口的數量,如果爲0則不出現interfaces類型

interfaces[interfaces_count] u2:記錄具體的接口指向,指向一個常量池對象,一般都指向CONSTANT_class_info類型

fields_count u2:記錄字段的數量,如果爲0則不出現fields類型

fields[fields_count] field_info:字段表集合

  • access_flags u2:字段訪問標誌

    • ACC_PUBLIC 0x0001
    • ACC_PRIVATE 0x0002
    • ACC_PROTECTED 0x0004
    • ACC_STATIC 0x0008
    • ACC_FINAL 0x0010
    • ACC_VOLATILE 0x0040
    • ACC_TRANSIENT 0x0080
    • ACC_SYNTHETIC 0x1000 標誌指示此字段是由編譯器生成的,不會出現在源代碼中。
    • ACC_ENUM 0x4000 枚舉類型
  • name_index u2: 字段名稱索引,指向CONSTANT_Utf8_info索引

  • descriptor_index u2:描述符索引,指向CONSTANT_Utf8_info索引

    • 字段描述符如何表示

      • B byte 字節型
      • C char 字符型
      • I int 整型
      • F float 浮點型
      • S short 短整型
      • J long 長整型
      • D double 雙精度浮點型
      • Z boolean 布爾型
      • L+對象全限定名 對象類型,如:String Ljava/lang/String
      • [+基本類型符合 數組類型,如int[] [I
      • V void 無類型
  • attributes_count u2:屬性個數

  • attributes[attributes_count]attribute_info->ConstantValue_attribute 字段表集合

    • attribute_name_index u2:屬性名稱索引,指向CONSTANT_Utf8_info 結構中的“ConstantValue”
    • attribute_length u2:值必須是2
    • constant_value_index:常量池條目索引必須適合該field

methods_count u2:記錄方法的數量,如果是類是一定存在的,如果是接口methods_count可能存在爲0,enum 最少4(有默認方法)

methods[methods_count] method_info 方法集合

  • access_flags u2:字段訪問標誌

    • ACC_PUBLIC 0x0001
    • ACC_PRIVATE 0x0002
    • ACC_PROTECTED 0x0004
    • ACC_STATIC 0x0008
    • ACC_FINAL 0x0010
    • ACC_SYNCHRONIZED 0x0020
    • ACC_BRIDGE 0x0040
    • ACC_VARARGS 0x0080
    • ACC_NATIVE 0x0100
    • ACC_ABSTRACT 0x0400
    • ACC_STRICT 0x0800
    • ACC_SYNTHETIC 0x1000 標誌指示此字段是由編譯器生成的,不會出現在源代碼中。
  • name_index u2:方法名稱索引,指向CONSTANT_Utf8_info索引的 or or 有效的非限定名稱

  • descriptor_index u2 方法描述索引(返回參數索引),指向CONSTANT_Utf8_info索引

  • attributes_count u2 方法中屬性個數

  • attributes attribute_info []

    • Code 執行方法 code_attribute_info

      • attribute_name_index u2 屬性名索引,指向CONSTANT_Utf8_info中的“Code”

      • attribute_length u4 屬性字節長度,不包括前6字節

      • max_stack u2 操作數棧的最大深度

      • max_locals u2 局部變量的最大數目,包含傳入參數的局部變量

        • long或double類型的值的最大局部變量索引是max_locals-2,max_locals-1是任何其他類型的值的最大局部變量索引
      • code_length u4 指令長度,表示代碼數組中的字節數,必須大於0 小於65536

      • code[code_length] u1*code_length 指令集合

      • exception_table_length 異常計數 u1

      • exception_table[exception_table_length] 異常集合 u8*exception_table_length

        • start_pc u2 開始指令地址
        • end_pc u2 結束指令地址
        • handler_pc u2 異常處理指令地址
        • catch_type u2 異常類型,指向CONSTANT_Class_info中catch時拋出的異常類
      • attributes_count u2 Code結構內屬性數

      • attributes attronites_info Code結構體內屬性集合

        • LinaNumberTable 源碼與指令關係 LinaNumberTable_info

          • attribute_name_index u2 屬性名稱,指向CONSTANT_Utf8_info中的“ LineNumberTable”

          • attribute_length u4 屬性長度,需要去掉初始的6字節

          • line_number_table_length u2 源碼指令關係表計數,表示LinaNumberTable的個數

          • line_number_table[line_number_table_ length] u4*line_number_table_length 源碼指令關係表數組

            • stact_pc u2 開始字節碼指令地址
            • line_number u2 源碼行號
        • LocalVariableTable 局部變量描述

          • attribute_name_index u2 屬性名稱,指向CONSTANT_Utf8_info中的“ LocalVariableTable”

          • attribute_length u4 屬性長度,需要去掉初始的6字節

          • local_variable_table_length u2 局部變量描述計數,表示LocalVariableTable的個數

          • local_variable_table[local_variable_table_ length] u10*local_variable_table_length 局部變量描述表集合 local_variable_ info

            • start_pc u2 開始字節碼指令地址
            • length u2 字節碼偏移量
            • name_index u2 局部變量名稱索引,指向CONSTANT_Utf8_info中的非限定名
            • descriptor_index u2 局部變量字段描述符
            • index u2 方法執行時,局部變量在棧幀中局部變量表的位置,如果是double,long 它佔用index,index+1
        • LocalVariableTypeTable 局部變量類型表,方法中使用了泛型變量,則會生成局部變量類型表,對泛型類型的局部變量,需要在LocalVariableTable Attribute和LocalVariableTypeTable Attribute中同時存在一項;而對非泛型類型的局部變量來說,只要在LocalVariableTable Attribute存在表項就可以

          如果方法中使用了泛型變量,則會生成 局部變量類型表;局部變量類型表的信息會覆蓋掉 局部變量表的信息;JDK5之後纔出現的 局部變量類型表,因爲JDK5之前不支持泛型,爲了兼容以前的老版本,不得不做了這個糟糕的設計;局部變量類型表在Hotspot中基本沒有任何作用,僅用於作爲Hotspot中的 局部變量表的 signature_cp_index字段賦值。

          • attribute_name_index u2 屬性名稱,指向CONSTANT_Utf8_info中的“ LocalVariableTypeTable”

          • attribute_length u4 屬性長度,需要去掉初始的6字節

          • local_variable_type_table_length u2 表示LocalVariableTypeTable的個數

          • local_variable_type_table[local_variable_type_table_length]

            • start_pc u2 開始字節碼指令地址
            • length u2 字節碼偏移量
            • name_index u2 局部變量名稱索引,指向CONSTANT_Utf8_info中的非限定名
            • signature_index u2 記錄該項代表的局部變量的字段簽名,指向CONSTANT_Utf8_info中
            • index u2 方法執行時,局部變量在棧幀中局部變量表的位置,如果是double,long 它佔用index,index+1
        • StackMapTable stack_map_frame 棧圖,爲了提高JVM在類型檢查的驗證過程的效率,只用於Class文件加載時的校驗

          • attribute_name_index u2 屬性名稱,指向CONSTANT_Utf8_info中的“ StackMapTable”

          • attribute_length u4 屬性長度,需要去掉初始的6字節

          • number_of_entries u2 表示entries表的成員數量

          • entries[number_of_entries] stack_map_frame

            • frame_type

              • same_frame

                • frame_type = SAME ;/ 0-63 /

                  • 該frame與前一個frame的局部變量區、操作數棧上對應位置的類型都完全一樣,這個值也是隱含的 offset_delta,offset_delta=frame_type的值
              • same_locals_1_stack_item_frame

                • frame_type = SAME_LOCALS_1_STACK_ITEM; / 64-127 /

                  • 當前幀與上一幀有相同的局部變量,操作數棧中的變量數目爲 1,隱式 offset_delta 爲 frame_type - 64
                • verification_type_info stack[1];

              • same_locals_1_stack_item_frame_extended

                • frame_type u1= SAME_LOCALS_1_STACK_ITEM_EXTENDED;/* 64-127 */

                  • 與same_locals_1_stack_item_frame的區別就是offset_delta是明確給定的
                • offset_delta u2

                • verification_type_info stack[1]

              • chop_frame

                • frame_type = CHOP/ 248- 250 /

                  • 當前幀與上一幀具有相同的局部變量,知識不存在最後k個局部變量,並且操作數棧爲空。k的值由公式251-frame_type給出,明確給出幀的offset_delta值
                • offset_delta u2

              • same_frame_extended

                • frame_type = SAME_FRAME_EXTENDED / 251/

                  • 局部變量信息和上一個幀相同,且操作數棧爲空,與same_frame不同的是offset_delta明確給定的
                • offset_delta u2

              • append_frame

                • frame_type = APPEND ; / 252-254 /

                  • 當前幀比上一幀多了k個局部變量,且操作數棧爲空,其中 k = frame_type -251
                • offset_delta u2

                • verification_type_info locals[frame_type - 251]

              • full_frame

                • frame_type = FULL_FRAME;/ 255 /

                  • 局部變量表和操作數棧做完整記錄
                • offset_delta

                • number_of_locals

                • verification_type_info locals[number_of_locals]

                • u2 number_of_stack_items

                • verification_type_info stack[number_of_stack_items];

    • Exceptions 拋出異常的方法 Exception_ attribute_info

      • attribute_name_index u2 屬性名稱,指向名稱爲Exceptions 的常量池

      • attribute_length u4 屬性長度

      • Number_of_exceptions u2 異常數量計數 ,表示有多少個異常名稱索引

      • exceptions_index_table[Number_of_ exceptions] u2*Number_of_ exceptions 異常常量池索引

        • 每兩個字節指向一個CONSTANT_Class_info類型 的常量池,全限定名稱
    • RuntimeVisibleParameterAnnotations 該方法在運行時可見的修飾該方法參數的Annotation,Java程序可以通過反射機制獲取這些Annotation中的值

      • attribute_name_index u2 屬性名稱,指向名稱爲RuntimeVisibleParameterAnnotations 的常量池

      • attribute_length u4 屬性長度

      • num_parameters u1 記錄該方法中的參數個數

      • parameter_annotations[num_parameters] annotation

        • type_index u2 指向CONSTANT_Utf8_info描述符

        • num_element_value_pairs

        • element_value_pairs[num_element_value_pairs] element_value_pairs

          • element_name_index,對應註解裏字段的字段名稱,指向CONSTANT_Utf8_info
          • value :加了註解的字段名爲 record
    • RuntimeInvisibleParameterAnnotations 記錄該方法在運行時不可見的修飾該方法參數的Annotation 結構與(RuntimeVisibleParameterAnnotations)相同

    • AnnotationDefault

      • attribute_name_index u2 屬性名稱,指向名稱爲AnnotationDefault 的常量池
      • attribute_length u4 屬性長度
      • default_value 代碼註解類型元素的默認值
    • MethodParameters

      • attribute_name_index u2 指向名稱爲“MethodParameters”的常量池

      • attribute_length u4 屬性長度

      • parameters_count u1 參數的數量

      • parameters[parameters_count] parameter

        • name_index u2 值必須爲0 或者指向常量池中的索引,如果爲0 則parameters指向不帶名稱的形參,如果非0 則必須指向CONSTANT_Utf8_info 中的非限定名

attributes_count u2 屬性表中的屬性數量,記錄原文件屬性信息,一般一個類具有一個

attributes[attributes_count] attribute_info 官方定義爲數組,實際上專屬類描述的只有

  • SourceFile 記錄源文件名稱

    • attribute_name_index u2 屬性名稱索引,指向值爲“ SourceFile”的常量池
    • attribute_length u4 屬性長度 值必須爲2
    • sourcefile_index 源文件名稱索引,指向值CONSTANT_Utf8_info 中類地址的常量池
  • InnerClasses 內部類列表

    • attribute_name_index u2 屬性名稱索引,指向值爲“ InnerClasses”的常量池
    • attribute_length 表示屬性的長度,不包括前六個字節。
    • number_of_classes 表明classes數組衝的個數
    • classes[number_of_classes] 表示一個非包成員的類,都明確對應CONSTANT_Class_info中的一個類
  • EnclosingMethod 僅當一個類爲局部類或者匿名類是才能擁有這個屬性

    • attribute_name_index u2 屬性名稱索引,指向值爲“ EnclosingMethod”的常量池
    • attribute_length u4 值必須爲4
    • class_index u2 指向CONSTANT_Class_info中的
    • method_index u2 如果沒有實現方法或構造函數的嵌套,則爲0 ,否則指向CONSTANT_NameAndType_info的索引,
  • SourceDebugExtension

    • attribute_name_index u2 屬性名稱索引,指向值爲“ SourceDebugExtension”的常量池
    • attribute_length u4 表示屬性的長度,不包括前六個字節。
    • debug_extension[attribute_length] u1*attribute_length
  • BootstrapMethods 這個屬性用於保存 invokedynamic 指令引用的引導方法限定符

    • attribute_name_index u2 屬性名稱索引,指向值爲“ BootstrapMethods”的常量池

    • attribute_length u4 表示屬性的長度,不包括前六個字節。

    • num_bootstrap_methods u2 數組中的引導方法限定符的數量

    • bootstrap_methods[num_bootstrap_methods]

      • bootstrap_method_ref u2

      • num_bootstrap_arguments u2

      • bootstrap_arguments[num_bootstrap_arguments] u2*num_bootstrap_arguments

        常量池在該索引處必須是下列結構之一:CONSTANT_String_info、CONSTANT_Class_info、CONSTANT_Integer_info、CONSTANT_Long_info、CONSTANT_Float_info、CONSTANT_Double_info、CONSTANT_MethodHandle_info 或 CONSTANT_MethodType_info

字段描述符

方法:Object m(int i, double d, Thread t) {…}

方法描述符(IDLjava/lang/Thread;)Ljava/lang/Object;

Constant value attribute types

Field access

XMind: ZEN - Trial Version

關注公衆號,每週都有新內容

獲取腦圖請回復公衆號“class文件解析”獲取PDF版本腦圖,需要補充的知識點可以進行留言,逐步進行完善。

最後感謝大家的關注

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章