這個class文件的解析,分析得有點太久了.前面介紹類魔數,次版本號,主板本號,常量池入口,常量池,訪問標志,類索引,父類索引和接口索引集合.下面就應該到字段表集合了.
緊接著接口索引集合的就是字段表的集合了.
字段表(field_info)用於描述接口或者類中聲明的變量.字段包括類級變量以及實例級變量,但是不包括在方法內部聲明的局部變量.
字段表的結構:
類型 名稱 數量 u2 access_flags 1 u2 name_index 1 u2 descriptor_index 1 u2 attributes_count 1 attribute_info attributes attributes_count字段修飾符放在access_flags項目中,它與類中的access_flags項目是非常相似的,都是一個u2的數據類型.
字段訪問標志:
標志名稱 標志值 含義 ACC_PUBLIC 0x00 01 字段是否為public ACC_PRIVATE 0x00 02 字段是否為private ACC_PROTECTED 0x00 04 字段是否為protected ACC_STATIC 0x00 08 字段是否為static ACC_FINAL 0x00 10 字段是否為final ACC_VOLATILE 0x00 40 字段是否為volatile ACC_TRANSTENT 0x00 80 字段是否為transient ACC_SYNCHETIC 0x10 00 字段是否為由編譯器自動產生 ACC_ENUM 0x40 00 字段是否為enum跟隨access_flags標志的是兩項索引值:name_index和descriptor_index,它們都是對常量池的引用,分別代表著字段的簡單名稱以及字段方法和方法的描述符.
描述符的作用是用來描述字段的數據類型,方法的參數列表(包括數量,類型以及順序)和返回值.根據描述符規則,基本數據類型以及代表無返回值的void類型都用一個大寫字符來表示,而對象類型則用字符加L加對象名的全限定名來表示.
描述符標志含義:
標志符 含義 B 基本數據類型byte C 基本數據類型char D 基本數據類型double F 基本數據類型float I 基本數據類型int J 基本數據類型long S 基本數據類型short Z 基本數據類型boolean V 基本數據類型void L 對象類型
對於數組類型,每一維度將使用一個前置的"["字符來描述.如一個定義為"java.lang.Stirng[ ]"類型的二維數組,將被記錄為:"[[Ljava/lang/Stirng",一個整型數組"int[]"將被記錄為"[I".
用描述符來描述方法時,按照先參數列表,後返回值的順序來描述,參數列表按照參數的嚴格順序放在一組小括號"()"之內.
字段表集合中不會列出從父類或者父接口中繼承而來的字段,但有可能列出原來Java代碼中不存在的字段,譬如在內部類中為了保持對外部類的訪問性,會自動添加指向外部類實例的字段.另外,在Java語言中字段是無法重載的,兩個字段的數據類型,修飾符不管是否相同,都必須使用不一樣的名稱,但是對於字節碼來講,如果連個字段的描述符不一致,那字段重名就是合法的.
下面繼續前面分析的class文件:
源文件:
javap分析出來的常量池:
分析:
從上圖中分析可以看到0x00 01表示字段表數據的個數,只有一個.0x00 02表示字段表的private修飾符,從上面的字段訪問標志表可以看到.0x00 05表示字段對應著第5個常量池,從javap分析出來的常量池,可以看到第5個常量池對應著m,再看源代碼我們定義的字段確實就是m.0x00 06表示描述符標識,對應著第6個常量池,為I,那麼在對應我們的訪問標識符含義表,I 對應著int數據類型,再看源代碼m的數據類型確實就是int.