獲取腦圖方式請看最下面!
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版本腦圖,需要補充的知識點可以進行留言,逐步進行完善。
最後感謝大家的關注