class文件包含了java虛擬機指令集 和 符號表 以及若干其餘輔助信息.
class文件是一組以8位字節爲基礎單位的二進制字節流
各個數據項按照順序緊湊的排列在Class文件中,中間沒有任何分隔符號
class文件採用相似 c結構體的格式存儲數據
數據類型只有兩種
無符號數 和 類c結構體的 表 表是由無符號數或者其餘的表構成的
整個class文件就是一張表
不管無符號數仍是表,當須要描述同一類型但數量不定的多個數據時,常常會使用一個前置的容量計數器用於指示接下來的數據個數,而後是若干個連續的數據項
class文件主要內容爲: 類自己的信息 字段 方法 常量池 以及方法中的Code屬性 再就是一些相關的輔助信息
類自己的信息類自己有一些必備的描述信息,好比類名 訪問修飾符 繼承關係等
字段用於描述接口或者類中聲明的變量
字段包括類變量以及實例變量,不包括局部變量 他有訪問標誌 名稱 描述符信息
方法用於描述方法表信息 相似字段 也有訪問標誌 名稱 描述符信息
常量池能夠理解爲Class文件的資源倉庫,因此他是與其餘項目關聯最多的數據類型
主要是兩大類: 字面量 以及符號引用
字面量接近java語言層面的常量概念 好比文本字符串 聲明爲final常量的值
符號引用包括:
類和接口的全限定名
字段的名稱和描述符
方法的名稱和描述符
虛擬機加載class文件的時候動態連接,因此class文件中不會保存方法的最終內存佈局, 還須要轉換
虛擬機運行時從常量池中得到對應的符號引用,而後在建立或者運行時解析翻譯到具體的內存地址中
Code屬性存放的Java方法的內容,位於方法method_info 內
存放的是java方法通過編譯器編譯成的字節碼指令 說白了存放的就是代碼的編譯後形式
概述:
class文件做爲JVM的"機器語言" 主要包括兩部分的信息,基礎信息以及附加信息
基礎信息爲源代碼中呈現的信息
類自身信息/字段/方法用於描述源代碼中的類/字段/方法
常量池中保存了資源信息,好比字段的名字 方法的描述符等
方法中的code屬性保存了方法中的代碼的執行邏輯
額外信息爲虛擬機執行過程當中或者字節碼指令執行所須要的信息
爲了保證虛擬機可以正確的加載class文件
另外虛擬機加載類還須要作一些額外的工做好比校驗信息等
字節碼指令的執行可能還須要一些額外的信息
這些額外的信息一般也是保存在常量池中或者以屬性的形式出現
|
struct 結構體名
{
類型名1 成員名1;
類型名2 成員名2;
.....
類型名n 成員名n;
};
|
struct student { char name[10]; char sex; int age; float score; };
cp_info{
u1 tag;
u1 info[ ]
}
class文件的形式是一張巨大的表,是一個二進制字節流
只有兩種數據表示形式 無符號數 以及 表(結構體 複合的數據結構)
各個數據項嚴格的按照順序存放,之間沒有填充或者對齊,這也是爲什麼編譯後代碼如此緊湊的緣由之一
基本數據類型爲: u1 u2 u4 u8
|
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]; }
public class HelloWorld { private int x; private String y; public void fun() { } public static void main(String[] args) { System.out.println("hello world"); } }
第四項 u2 constant_pool_count![]() 十六機制27 十進制39 能夠看到javap解析後的Constant pool:中總共有從#1 到 #38 常量池計數器constant_pool_count的值等於常量表中的成員數加1 常量池標的索引值只有大於0 且小於constant_pool_count時纔有效 因此此處解析也是對的 |
ClassFile { u4 magic;//惟一做用是肯定這個文件是否爲一個能被虛擬機所接受的class文件。魔數值固定爲0xCAFEBABE,不會改變 u2 minor_version;//惟一做用是肯定這個文件是否爲一個能被虛擬機所接受的class文件。魔數值固定爲0xCAFEBABE,不會改變 u2 major_version;//主版本號 u2 constant_pool_count;//常量池計數 值等於常量池表中的成員個數加1 cp_info constant_pool[constant_pool_count-1];//常量池 1~ constant_pool_count-1 爲索引 u2 access_flags;//訪問標誌以及類型信息 u2 this_class;//當前類索引 指向常量池中一個CONSTANT_Class_info u2 super_class;//父類索引 0 或者指向常量池中一個CONSTANT_Class_info u2 interfaces_count;//直接超接口數量 u2 interfaces[interfaces_count];//接口表 u2 fields_count;//字段個數 static類變量或者非sttic的實例變量 不包括繼承的 field_info fields[fields_count];//字段表 u2 methods_count;//方法個數 全部方法 但不包括繼承而來的 method_info methods[methods_count];//方法表 u2 attributes_count;//屬性個數 attribute_info attributes[attributes_count];/屬性表 }
形式是
FieldType
|
B | byte | [基本類型] 有符號的字節數組 |
C | char | [基本類型] 基本多語種平面中的Unicode代碼點 UTF-16 |
D | double | [基本類型] 雙精度浮點數 |
F | float | [基本類型] 單精度浮點數 |
I | int | [基本類型] 整型數 |
J | long | [基本類型] 長整數 |
S | short | [基本類型] 有符號短整數 |
Z | boolean | [基本類型] 布爾值true/false |
L ClassName; | L ClassName; | [對象類型] ClassName類的實例 |
[ | reference | [數組類型] 一維數組 |
形式是
( {ParameterDescriptor} ) ReturnDescriptor
注意: {} 不是一部分,是想表達和數組似的,也多是多個
|
名稱 | 值 | |
ACC_PUBLIC | 0x0001 | 聲明爲public 包外訪問 |
ACC_FINAL | 0x0010 | final 不容許子類 |
ACC_SUPER | 0x0020 | 調用invokespecial 須要處理父類 |
ACC_INTERFACE | 0x0200 | 這是一個接口 |
ACC_ABSTRACT | 0x0400 | abstract 抽象的不能被實例化 |
ACC_SYNTHETIC | 0x1000 | class文件並不是由java源代碼生成 |
ACC_ANNOTATION | 0x2000 | 註解 |
ACC_ENUM | 0x4000 | 枚舉 |
主要分爲兩類 字面量 符號引用
字面量相似java語言層面的含義 文本字符串 聲明爲final 的常量值
符號引用包括:
類和接口的全限定名
字段的名稱和描述符
方法的名稱和描述符
常量池包含了class文件結構及其子結構中引用的全部的,字符串常量,類或者接口名,字段名,以及其餘常量
|
基本數據類型,好比 int long的描述形式,
雖然class文件是二進制字節流,最小爲u1 可是這些基本數據類型在邏輯意義上來講,纔是最小的描述單位
|
用於表述, 用於描述各個部分包含的邏輯內容的表 "結構體" 複合形式的數據類型結構
|
中間的映射結構表 至關於數據庫中的中間關係表
|
cp_info{
u1 tag;
u1 info[];
}
CONSTANT_Class | 7 |
CONSTANT_Fieldref | 9 |
CONSTANT_Methodref | 10 |
CONSTANT_InterfaceMethodref | 11 |
CONSTANT_String | 8 |
CONSTANT_Integer | 3 |
CONSTANT_Float | 4 |
CONSTANT_Long | 5 |
CONSTANT_Double | 6 |
CONSTANT_NameAndType | 12 |
CONSTANT_Utf8 | 1 |
CONSTANT_MethodHandle | 15 |
CONSTANT_MethodType | 16 |
CONSTANT_InvokeDynamic | 18 |
字符串常量 |
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
|
tag是CONSTANT_Utf8 1 字符串採用改進過的UTF-8編碼表示 接下來是編碼後的字符串佔用字節數以及字符串 class文件中的方法字段名稱都是此類型 |
int整型 4字節 |
CONSTANT_Integer_info {
u1 tag;
u4 bytes;
}
|
tag爲CONSTANT_Integer 3 大端排序的int值 |
單精度浮點型 float 4字節 |
CONSTANT_Float_info {
u1 tag;
u4 bytes;
}
|
tag爲CONSTANT_Float 4 大端排序 IEEE754單精度格式 的floa值 |
long 長整型 8字節 |
CONSTANT_Long_info {
u1 tag;
u4 high_bytes;
u4 low_bytes;
}
|
tag爲CONSTANT_Long 5 大端排序的long值 |
雙精度浮點型 double 8字節 |
CONSTANT_Double_info {
u1 tag;
u4 high_bytes;
u4 low_bytes;
}
|
tag爲CONSTANT_Double 6 大端排序的 double值 |
CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
}
|
tag爲 CONSTANT_NameAndType (12) NameAndType 就是名稱和類型的意思 對於方法 / 字段 來講, 他們都有變量名稱或者方法名稱 他們也都有變量類型和方法簽名(方法的類型) NameAndType 是做爲一箇中間表形式的數據結構 字段/方法中都有一個索引指向他,他又指向了實際的名稱和類型 不論是方法名稱仍是字段名稱 不論是方法簽名仍是字段類型都是字符常量的形式 name_index 和 descriptor_index 指向的都是CONSTANT_Utf8_info |
String類型的常量對象
|
CONSTANT_String_info {
u1 tag;
u2 string_index;
}
|
tag爲CONSTANT_String 8
他表示的是String類型的數據,咱們知道String是常量
字符串常量是用CONSTANT_Utf8_info進行表示的
因此 String_index指向的就是對應的CONSTANT_Utf8_info的"行號"
|
方法類型 |
CONSTANT_MethodType_info {
u1 tag;
u2 descriptor_index;
}
|
CONSTANT_MethodType 16 CONSTANT_NameAndType_info 是一個用於字段或者方法結構中的中間結構,包含了名稱和類型 CONSTANT_MethodType_info 僅僅表示的就是方法簽名 方法簽名對應的是CONSTANT_Utf8_info 因此descriptor_index 指向 方法類型描述符的CONSTANT_Utf8_info |
類或接口 |
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
|
tag 爲CONSTANT_Class 7 名稱天然是字符串常量也就是CONSTANT_Utf8_info 因此 name_index指向常量池中的 CONSTANT_Utf8_info |
字段 |
CONSTANT_Fieldref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
|
CONSTANT_Fieldref 9 class_index 表示當前字段 對應或者說所屬的 類或者接口 類和接口均可能 class_index指向CONSTANT_Class_info name_and_type_index 表示當前字段的名稱和類型 name_and_type_index指向CONSTANT_NameAndType_info |
方法 |
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
|
CONSTANT_Methodref 10 class_index 表示當前方法 對應或者說所屬的類,必須是類,不能是接口 class_index指向CONSTANT_Class_info
name_and_type_index 表示當前方法的名稱和方法簽名
name_and_type_index指向CONSTANT_NameAndType_info
|
接口方法 |
CONSTANT_InterfaceMethodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
|
CONSTANT_InterfaceMethodref 11 class_index 表示當前方法 對應或者說所屬的接口,必須是接口 不能是類 class_index指向CONSTANT_Class_info
name_and_type_index 表示當前方法的名稱和方法簽名
name_and_type_index指向CONSTANT_NameAndType_info
|
方法調用 |
CONSTANT_MethodHandle_info {
u1 tag;
u1 reference_kind;
u2 reference_index;
}
|
CONSTANT_MethodHandle 15 方法調用,顧名思義也就是描述 方法的調用 對於一個方法調用來講,方法可能有不一樣的類型,不一樣的類型有不一樣的操做對象 reference_kind 正是描述方法的調用類型 reference_index 描述的是方法的操做目標 reference_kind 的值爲1~9 他的類型決定了方法句柄的類型 句柄類型的值表示方法句柄中字節碼行爲 |
用於表示invokedynamic指令 |
CONSTANT_InvokeDynamic_info {
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}
|
tag爲CONSTANT_InvokeDynamic 18 CONSTANT_InvokeDynamic_info是爲了字節碼指令 invokedynamic 使用的 invokedynamic是爲了更好的支持動態類型語言,Java7經過JSR292給JVM增長的一條新的字節碼指令 bootstrap_method_attr_index 的值必須是對當前Class文件中引導方法表的bootstrap_methods[] 數組的有效索引 name_and_type_index 指向CONSTANT_NameAndType 表示方法名和方法描述符 |
字段 |
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
|
每一個字段都由field_info結構定義 同一個class文件中不會有兩個字段同時具備相同的字段名和描述符 access_flags 表示字段訪問權限和基本屬性 name_index指向字段的名字 CONSTANT_utf8_info descriptor_index 指向字段描述符CONSTANT_utf8_info 字段field 包含屬性表,屬性表結構的狀況稍後介紹 |
ACC_PUBLIC | 0x0001 | 字段是否爲public 能夠包外訪問 |
ACC_PRIVATE | 0x0002 | 字段是否爲private 只能本類訪問 |
ACC_PROTECTED | 0x0004 | 字段是否爲protected 子類能夠訪問 |
ACC_STATIC | 0x0008 | 字段是否爲static |
ACC_FINAL | 0x0010 | 字段是否爲final |
ACC_VOLATILE | 0x0040 | 字段是否爲volatile |
ACC_TRANSIENT | 0x0080 | 字段是否爲transient |
ACC_SYNTHETIC | 0x1000 | 字段是否由編譯器產生 |
ACC_ENUM | 0x4000 | 字段是否爲enum |
方法 |
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
|
全部方法,包括實例初始化方法以及類或者接口初始化方法 一個class文件中不會有兩個方法具備相同的方法名和描述符 name_index 指向方法名字 CONSTANT_Utf8_info descriptor_index 表示方法描述符 指向 CONSTANT_Utf8_info 方法也有屬性表 |
ACC_PUBLIC | 0x0001 | 方法是否爲public 包外訪問 |
ACC_PRIVATE | 0x0002 | 方法是否爲private 當前類訪問 |
ACC_PROTECTED | 0x0004 | 方法是否爲protected 子類訪問 |
ACC_STATIC | 0x0008 | 方法是否爲static |
ACC_FINAL | 0x0010 | 方法是否爲final |
ACC_SYNCHRONIZED | 0x0020 | 方法是否爲synchronized |
ACC_BRIDGE | 0x0040 | 方法是否爲 編譯器爲了字節碼兼容自動生成的bridge方法 |
ACC_VARARGS | 0x0080 | 方法是否爲變長參數 |
ACC_NATIVE | 0x0100 | 方法是否爲native 本地方法 |
ACC_ABSTRACT | 0x0400 | 方法是否爲abstract 無實現代碼 |
ACC_STRICT | 0x0800 | 方法是否爲strictfp 使用FP-strict浮點模式 |
ACC_SYNTHETIC | 0x1000 | 方法是否爲編譯器自動產生而不是由源代碼編譯而來 |
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
1.對於JVM 正確解讀class文件起關鍵做用的5個屬性
• ConstantValue
• Code
• StackMapTable
• Exceptions
• BootstrapMethods
|
2.對JavaSE 平臺類庫正確解讀class文件起關鍵做用的12個屬性
• InnerClasses
• EnclosingMethod
• Synthetic
• Signature
• RuntimeVisibleAnnotations
• RuntimeInvisibleAnnotations
• RuntimeVisibleParameterAnnotations
• RuntimeInvisibleParameterAnnotations
• RuntimeVisibleTypeAnnotations
• RuntimeInvisibleTypeAnnotations
• AnnotationDefault
• MethodParameters
|
對JVM或者JavaSE平臺類庫可以正確解讀class文件 雖然不起關鍵做用,可是卻能夠做爲實用工具來使用的6個屬性
• SourceFile
• SourceDebugExtension
• LineNumberTable
• LocalVariableTable
• LocalVariableTypeTable
• Deprecated
|
屬性 | 位置 | 備註 | 首次出現版本號 |
SourceFile
|
ClassFile | 表示class文件的源文件名稱 類獨有屬性 |
45.3 |
InnerClasses
|
ClassFile | 內部類相關信息 類獨有屬性 |
45.3 |
EnclosingMethod
|
ClassFile | class爲局部類或者匿名類才具備 類獨有屬性 |
49.0 |
SourceDebugExtension
|
ClassFile | 可選/保存擴展調試信息/最多一個 類獨有屬性 |
49.0 |
BootstrapMethods | ClassFile |
與 invokedynamic指令
常量池中CONSTANT_InvokeDynamic_info
相關
類獨有屬性
|
51.0 |
ConstantValue | field_info | fina修飾的字段的常量值 字段獨有屬性 |
45.3 |
Code | method_info | java程序方法體中的代碼通過javac編譯器處理後 最終變爲字節碼指令存儲在Code屬性內 Code屬性出如今方法表的屬性集合中 抽象類和接口不存在code屬性 包含了方法的java虛擬機指令及相關輔助信息 方法獨有屬性 |
45.3 |
Exceptions | method_info | 方法可能拋出的已檢查異常列表 方法獨有屬性 |
45.3 |
RuntimeVisibleParameterAnnotations,
RuntimeInvisibleParameterAnnotations
|
method_info | 形參上的運行時的註解信息類型 分爲可見和不可見兩種類型 方法獨有屬性 |
49.0 |
AnnotationDefault | method_info | method_info表示註解類型中的元素時 記錄這個元素的默認值 方法獨有屬性 |
49.0 |
MethodParameters | method_info | 形參相關信息,好比參數名稱 方法獨有屬性 |
52.0 |
Synthetic | classFile field_info method_info |
Synthetic 標誌編譯器生成 類 字段 方法均可能由編譯器生成 因此三種都有此屬性 |
45.3 |
Deprecated | classFile field_info method_info |
語義同@Deprecated 顯然能夠標註在類/接口/字段/方法上 因此三種都有此屬性 |
45.3 |
Signature |
classFile
field_info
method_info
|
泛型信息 類接口 字段 方法 都有可能有類型參數 因此三種都有此屬性 |
49.0 |
RuntimeVisibleAnnotations,
RuntimeInvisibleAnnotations
|
classFile
field_info
method_info
|
類 方法 字段上 運行時註解的可見性 分爲可見不可見兩種類型 三種都有此屬性 |
49.0 |
LineNumberTable | Code | 調試用信息 用於調試器肯定源文件中給定行號所表示的內容,對應於虛擬機中code[]數組中的哪一部分 也就是行號與字節碼指令的對應關係 |
45.3 |
LocalVariableTable | Code | 調試用信息 調試器執行方法過程當中能夠用它來肯定某個局部變量的值 |
45.3 |
LocalVariableTypeTable | Code |
調試用信息
調試器執行方法過程當中能夠用它來肯定某個局部變量的值
|
49.0 |
StackMapTable | Code | 虛擬機類型檢查驗證使用信息 | 50.0 |
RuntimeVisibleTypeAnnotations,
RuntimeInvisibleTypeAnnotations
|
classFile
field_info
method_info
|
類/方法/字段聲明所使用的類型上面的運行時註解可見性 分爲可見/不可見兩種 三種都有此屬性 |
52.0 |
classFile |
SourceFile
InnerClasses
EnclosingMethod
SourceDebugExtension
BootstrapMethods
Synthetic
Deprecated
Signature
RuntimeVisibleAnnotations,
RuntimeInvisibleAnnotations
RuntimeVisibleTypeAnnotations,
RuntimeInvisibleTypeAnnotations
|
field_info |
ConstantValue
Synthetic
Deprecated
Signature
RuntimeVisibleAnnotations,
RuntimeInvisibleAnnotations
RuntimeVisibleTypeAnnotations,
RuntimeInvisibleTypeAnnotations
|
method_info |
Code
Exceptions
RuntimeVisibleParameterAnnotations,
RuntimeInvisibleParameterAnnotations
AnnotationDefault
MethodParameters
Synthetic
Deprecated
Signature
RuntimeVisibleAnnotations,
RuntimeInvisibleAnnotations
RuntimeVisibleTypeAnnotations,
RuntimeInvisibleTypeAnnotations
|
Code |
LineNumberTable
LocalVariableTable
LocalVariableTypeTable
StackMapTable
|
ConstantValue_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;
}
|
Code_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
|
ps:
虛擬機棧是線程私有的,每建立一個線程,虛擬機就會爲這個線程建立一個虛擬機棧
虛擬機棧表示Java方法執行的內存模型,每調用一個方法就會爲每一個方法生成一個棧幀(Stack Frame),用來存儲局部變量表、操做數棧、動態連接、方法出口等信息。
每一個方法被調用和完成的過程,都對應一個棧幀從虛擬機棧上入棧和出棧的過程。
虛擬機棧的生命週期和線程是相同的
|
StackMapTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_entries;
stack_map_frame entries[number_of_entries];
}
|
union stack_map_frame {
same_frame;
same_locals_1_stack_item_frame;
same_locals_1_stack_item_frame_extended;
chop_frame;
same_frame_extended;
append_frame;
full_frame;
}
|
Exceptions_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_exceptions;
u2 exception_index_table[number_of_exceptions];
}
|
BootstrapMethods_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 num_bootstrap_methods;
{ u2 bootstrap_method_ref;
u2 num_bootstrap_arguments;
u2 bootstrap_arguments[num_bootstrap_arguments];
} bootstrap_methods[num_bootstrap_methods];
}
|
InnerClasses_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_classes;
{ u2 inner_class_info_index;
u2 outer_class_info_index;
u2 inner_name_index;
u2 inner_class_access_flags;
} classes[number_of_classes];
}
|
ACC_PUBLIC | 0x0001 | 內部類是否爲public |
ACC_PRIVATE | 0x0002 | 內部類是否爲private |
ACC_PROTECTED | 0x0004 | 內部類是否爲protected |
ACC_STATIC | 0x0008 | 內部類是否爲static |
ACC_FINAL | 0x0010 | 內部類是否爲final |
ACC_INTERFACE | 0x0200 | 內部類是否爲interface |
ACC_ABSTRACT | 0x0400 | 內部類是否爲abstract |
ACC_SYNTHETIC | 0x1000 | 內部類是否爲編譯器自動生成 |
ACC_ANNOTATION | 0x2000 | 內部類是否爲註解 |
ACC_ENUM | 0x4000 | 內部類是否爲枚舉 |
Synthetic_attribute {
u2 attribute_name_index;
u4 attribute_length;
}
|
Signature_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 signature_index;
}
|
EnclosingMethod_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 class_index;
u2 method_index;
}
|
RuntimeVisibleAnnotations_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 num_annotations;
annotation annotations[num_annotations];
}
|
RuntimeInvisibleAnnotations_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 num_annotations;
annotation annotations[num_annotations];
}
|
annotation {
u2 type_index;
u2 num_element_value_pairs;
{ u2 element_name_index;
element_value value;
} element_value_pairs[num_element_value_pairs];
}
type_index 用來表示一個字段描述符,字段描述符表示一個註解類型
和當前annotation 結構所表示的註解一致
num_element_value_pairs 表示註解中的鍵值對 (註解中的參數都是鍵值對) 的個數
element_value_pairs 表明真正的鍵值對
它包括
element_name_index表示鍵
element_value 表示值
element_value {
u1 tag;
union {
u2 const_value_index;
{ u2 type_name_index;
u2 const_name_index;
} enum_const_value;
u2 class_info_index;
annotation annotation_value;
{ u2 num_values;
element_value values[num_values];
} array_value;
} value;
}
element_value 表示一個聯合體
tag 使用u1 來表示鍵值對中的值是什麼類型
也就是決定了鍵值對中 值的格式與value 中的哪一項相符合
聯合體總共有五種
const_value_index
enum_const_value
class_info_index
annotation_value
array_value
|
B | byte | const_value_index | CONSTANT_Integer |
C | char | const_value_index | CONSTANT_Integer |
D | double | const_value_index | CONSTANT_Double |
F | float | const_value_index | CONSTANT_Float |
I | int | const_value_index | CONSTANT_Integer |
J | long | const_value_index | CONSTANT_Long |
S | short | const_value_index | CONSTANT_Integer |
Z | boolean | const_value_index | CONSTANT_Integer |
s | String | const_value_index | CONSTANT_Utf8 |
e | Enum類型 | enum_const_value | 不適用 |
c | Class | class_info_index | 不適用 |
@ | Annotation類型 | annotation_value | 不適用 |
[ | Array 類型 | array_value | 不適用 |
const_value_index 表示原始類型的常量值 或者String類型的字面量 |
enum_const_value 表示一個枚舉常量
type_name_index 指向CONSTANT_Utf8_info 枚舉常量類型的二進制名稱的內部形式
const_name_index 指向CONSTANT_Utf8_info 枚舉常量的簡單名稱
|
class_info_index 表示類字面量 CONSTANT_Utf8_info 用於表示返回描述符 返回描述符給出了與該element_value結構所表示的類字面量相對應的類型
若是類字面量是C. class,且C是類、接口或數組類型的名字,那麼對應的類型就是C。常量池中的返回描述符會是ObjectType 或者ArrayType
若是類字面量是p. class,且p是原始類型的名稱,那麼對應的類型就是p 常量池中的返回描述符會是一個BaseType
若是類字面量是void. class,那麼對應的類型就是void。常量池中的返回描述符會是V.
好比Object.class 對應於類型Object 因此常量池中就是Ljava/lang/Object; 而 int.class對應於類型int 常量池中就是I(大寫的i )
|
annotation_value 表示鍵值對中裏面的值自己又是一個註解 |
array_value 表示鍵值對的 值 是一個數組
num_values 給出了當前element_value結構所表示的數組的成員數量
values 每一個成員對應了當前element_value 結構所表示的數組中的一個元素
|
RuntimeVisibleTypeAnnotations_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 num_annotations;
type_annotation annotations[num_annotations];
}
|
RuntimeInvisibleTypeAnnotations_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 num_annotations;
type_annotation annotations[num_annotations];
}
|
type_annotation {
u1 target_type;
union {
type_parameter_target;
supertype_target;
type_parameter_bound_target;
empty_target;
method_formal_parameter_target;
throws_target;
localvar_target;
catch_target;
offset_target;
type_argument_target;
} target_info;
type_path target_path;
u2 type_index;
u2 num_element_value_pairs;
{ u2 element_name_index;
element_value value;
} element_value_pairs[num_element_value_pairs];
}
|
RuntimeVisibleParameterAnnotations_attribute {
u2 attribute_name_index;
u4 attribute_length;
u1 num_parameters;
{ u2 num_annotations;
annotation annotations[num_annotations];
} parameter_annotations[num_parameters];
}
|
RuntimeInvisibleParameterAnnotations_attribute {
u2 attribute_name_index;
u4 attribute_length;
u1 num_parameters;
{ u2 num_annotations;
annotation annotations[num_annotations];
} parameter_annotations[num_parameters];
}
|
AnnotationDefault_attribute {
u2 attribute_name_index;
u4 attribute_length;
element_value default_value;
}
|
name_index 要麼是0要麼指向CONSTANT_Utf8_info 表示一個有效的非限定名 用來指代某個形式參數
access_flags ACC_FINAL 0x0010 形參爲final
ACC_SYNTHETIC 0x1000 形參沒有顯式或者隱式的在源代碼中聲明,由編譯器生成
ACC_MANDATED 0x8000 形參是隱式聲明,也就是編程語言規範對全部的編譯器的要求必須生成
MethodParameters_attribute {
u2 attribute_name_index;
u4 attribute_length;
u1 parameters_count;
{ u2 name_index;
u2 access_flags;
} parameters[parameters_count];
}
|
SourceFile_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 sourcefile_index;
}
|
SourceDebugExtension_attribute {
u2 attribute_name_index;
u4 attribute_length;
u1 debug_extension[attribute_length];
}
|
LineNumberTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 line_number_table_length;
{ u2 start_pc;
u2 line_number;
} line_number_table[line_number_table_length];
}
|
LocalVariableTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 local_variable_table_length;
{ u2 start_pc;
u2 length;
u2 name_index;
u2 descriptor_index;
u2 index;
} local_variable_table[local_variable_table_length];
}
|
LocalVariableTypeTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 local_variable_type_table_length;
{ u2 start_pc;
u2 length;
u2 name_index;
u2 signature_index;
u2 index;
} local_variable_type_table[local_variable_type_table_length];
}
|
Deprecated_attribute {
u2 attribute_name_index;
u4 attribute_length;
}
|