標籤:const 長度 產生 相關 常量池 注意 handle integer 枚舉類
每一個class位元組碼檔案都唯一對應一個類或介面,class檔案中記錄中類或介面的基本資料,但反之不成立,不是每一個類或介面都有一個唯一對應的位元組碼檔案,首先類或介面的位元組碼可以不以檔案的方式儲存,可以直接從記憶體中產生位元組碼,而不產生.class檔案,動態代理的原理就是直接記憶體中產生位元組碼流,根據載入位元組碼流進行類載入操作,類執行個體化,組建代理程式對象。
位元組碼檔案記錄的資訊:魔術,class檔案主次版本,常量池數量及常量池表,類或介面的訪問標誌,類索引,超類索引,介面數量及介面表,欄位數量及欄位表,方法數量及方法表,屬性屬性及屬性工作表
魔術:四個位元組,用於定義此位元組碼檔案是否符合虛擬機器規範,保證位元組碼檔案不會威脅虛擬機器的安全,若為cafebabe則表示位元組碼符合虛擬機器規範
主次版本號碼:四個位元組,前兩位元組表示次版本號碼,後兩位元組表示主要版本號,用於定義編譯的位元組碼檔案格式版本,第版本虛擬機器拒絕運行高版本位元組碼檔案,但高版本虛擬機器會向下相容低版本位元組碼檔案
常量池數量及常量池表:這部分主要統計類或介面的字面量和符號引用,用於每個類或介面擁有的字面量和符號引用屬性不一定相同,所有需要兩個位元組的長度來表示常量池數目,常量池數目計數從1開始,比如類或介面中總共有兩個字面量符號引用,則常量池數目為2,注意,不是從0開始計數,0可能另有用處,可以用來表示類或介面中未出現的引用,用來表示超級父類java.long.Object全限定名的索引,常量池表是一個數組,一共有18種類型,每一種類型有一個tag屬性與之對應,constant_utf8_info用於表示文本字串,類和介面全限定名,欄位名稱及描述符,方法名稱及描述符等常量資訊,constant_integer_info用於儲存int類型的常量資訊,只儲存int類型的值,不儲存其他符合引用資訊,比如 final int a=1 符號引用資訊為a,值為1,constant_float_info用於儲存float類型常量資訊,也是只儲存float值,不儲存引用資訊,constant_long_info用於儲存long類型的常量資訊,constant_double_info用於儲存double類型的常量資訊,constant_class_info用於儲存指向常量池列表constant_unf8_info類和介面全限定名的有效引用,constant_string_info用於儲存指定常量池列表constant_utf8_info某常量項的有效索引,指向文本字串,constant_fieldref_info用於儲存指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_methodref_info用於儲存指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_interfacemethodref_info用於儲存指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_nameandtype_info用於儲存指向常量池列表constant_utf8_info常量項的有效索引,可以通過所有找到對應類及描述符,constant_methodtype_info用於儲存指向常量池constant_utf8_info常量項,表示方法類型,找到對應的方法描述符,constant_methodhandle_info用於表示方法控制代碼,屬性reference_kind表示方法控制代碼的類型,1-4表示為欄位建立的方法控制代碼,5-8表示為類方法(構造、執行個體、靜態)建立的控制代碼,9表示為介面方法建立的控制代碼,reference_index屬性指向根據reference_kind對應的常量池列表,constant_invokedynamic_info用於儲存當前位元組碼檔案中引導方法bootstrap_method數組的有效索引和指向常量池constant_nameandtype_info常量項的有效索引
訪問標誌:兩個位元組,用於定義位元組碼檔案所表示的類或介面的存取權限,如判斷是類還是介面,類是否被abstract修飾,類是否被final修飾, acc_interface表示是介面,acc_annotation表示是註解類型,acc_enum表示是枚舉類型,acc_public 表示類或介面是public存取權限,acc_final表示類不允許被繼承,acc_abstract表示類為抽象類別,acc_super表示類調用執行個體方法時需進行特殊操作
類索引及父類索引:四個位元組,用於儲存指向常量池constant_class_info對應的有效索引,而constant_class_info儲存常量池列表的constant_utf8_info常量項索引,根據此索引可找到類和父類的全限定名
介面數量及介面表:介面屬性用於儲存當前類或介面的直接超類介面數量,介面表是一個數組,記住,只有常量池表從1開始計數,其餘都是從數組下表0開始計數,介面表數組的每一個數組元素儲存此類或介面的直接超類介面的有效索引,根據此索引找到constant_class_info對應的常量項,根據constant_class_info可找到對應直接超類介面的全限定名
欄位數量及欄位表:欄位數量用於儲存類或介面的欄位數目,包括類欄位和執行個體欄位,欄位表為一個數組,每一個數組元素都相當於一個field_info結構的對象,field_info結構包含欄位完整資訊:欄位標識符,欄位存取修飾詞,欄位是類欄位還是執行個體欄位,欄位是否為常量等,注意:此處欄位表示當前類或介面的欄位,不包括從超類或介面繼承的欄位,java文法規範不允許同一個類或介面中出現同一欄位名的不同欄位,但是class檔案中卻可以允許出現相同欄位名的不同欄位,只有欄位的描述符不同即可,field_info結構屬性:access_flags用於儲存欄位的訪問標誌,acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile等,注意:acc_final與acc_volatile不能同時出現在同一欄位,name_index指向常量池constant_utf8_info常量項的有效索引,擷取當前欄位的簡單名稱,descriptor_index指向常量池constant_utf8_info常量項的有效索引,擷取當前欄位的描述符,attribute_count,attributes[attributes_count]這兩項表示欄位的屬性資訊,用於描述欄位相關資訊,attribute數組每一個元素都是一個attribute_info結構的元素
方法數量及方法表:方法數量用於儲存當前類或介面的方法數目,包括執行個體方法,類方法,抽象方法,方法表是一個數組,每一個數組元素都是一個method_info結構,method_info結構包含方法的完整資訊:方法描述符,存取修飾詞,是否為final方法,是否為abstract方法等,注意:此處的方法數組只是表示當前類或介面的所有方法,並不包括從超類及父介面繼承來的方法,java文法規範java類或介面中不允許出現方法簽名完全一樣的方法同時出現,會編譯報錯,而位元組碼層面卻允許方法簽名完全相同的方法同時出現,只需要保證方法的傳回值類型不同,method_info結構屬性與field_info一致,但acc_flags類型不盡相同,注意acc_abstract不能與acc_final,acc_static,acc_private,acc_synchronized,acc_native同時使用,介面方法中只能使用acc_public,acc_abstract,此處我有一個疑問,介面中default方法有沒有對應的訪問標誌,注意:<init>方法只能使用acc_private,acc_protected,acc_public訪問標誌
屬性數量及屬性工作表:屬性數量表示當前位元組碼檔案中attribute_info表數目,屬性工作表是一個數組,每一個數組元素都是attribute_info結構,attribute_info結構表示屬性的完整資訊:第一項指向常量池constant_utf8_info某常量項的有效索引,根據此索引可找到屬性對應名稱,屬性可以出現在classFile,欄位表,方法表中,用以描述相關資訊,attribute_info結構完整資訊:attribute_name_index指向常量池constant_utf8_info常量項的有效索引,擷取屬性名稱,attribute_length用於指明info數組長度,info[attribute_length]用於儲存屬性的資料資訊,必須實現的資料資訊:Code,ConstantValue,Exceptions, code屬性用於描述method_info的具體相關資訊,attribute_name_index指向常量池constant_utf8_info常量項的有效索引,擷取屬性名稱,即code,attribute_length表示attribute表示attribute_info長度,不包括attribute_name_index和attribute_length的初始6位元組,max_stack描述當前方法最大棧深度,max_locals描述當前方法的局部變數表,code_length表示code數組長度,code[]表示當前方法編譯後的位元組碼, ContantVaue位於field_info結構中,用於通知虛擬機器對類變數進行初始化,即欄位需要被acc_static修飾,當前類常量不需要ContantValue通知虛擬機器執行初始化,早就執行好了,執行個體欄位此時不需要初始化,
java 位元組碼檔案詳解