理解Class文件結構

*.class 是 *.java 編譯後的產物,我們來用一個最小的例子看一下class的文件結構

源代碼

package sample.asm.readclass;

public class Test {
    private String name;
}

反編譯

class文件結構(The Java Virtual Machine Specification Java SE 7 Edition)

注意,比如cp_info,cp_info表示常量池,上圖中用 constant_pool[constant_pool_count-1]的方式來表示常量池有constant_pool_count-1個常量,它 這裏是採用數組的表現形式,但是大家不要誤以爲所有的常量池的常量長度都是一樣的,其實這個地方只是爲了方便描述採用了數組的方式,但是這裏並不像編程語 言那裏,一個int型的數組,每個int長度都一樣。

(1)魔數:CAFEBABE

(2)minor_version:0000

(3)major_version:0034

(4)常量池的數量000F (十進制:15)

常量池的數量是constant_pool_count-1,爲什麼減一,是因爲索引0表示class中的數據項不引用任何常量池中的常 量。

(5)常量池

每個常量都有一個u1類型的tag標識來表示 常量的類型,第一個常量的類型是0x0A,轉換成二級制是10,有上面的關於常量類型的描述可知tag爲10的常量是Constant_Methodref_info


tag class_index name_and_type_index
0A 0003 000C
--- #3(#14 java/lang/Object) #12(#6#7 <init>()V)

(6)u2 access_flags 0021

表示類或者接口方面的訪問信息,比如Class表示的是類還是接口,是否爲public,static,final等。0x0021=0x0001|0x0020 也即ACC_PUBLIC 和 ACC_SUPER爲真,其中ACC_PUBLIC大家好理解,ACC
_SUPER是jdk1.2之後編譯的類都會帶有的標誌。

(7)u2 this_class 0002

表示類的索引值,用來表示類的全限定名稱 sample/asm/readclass/Test

(8)u2 super_class:0003

表示當前類的父類的索引值 java/lang/Object

(9)interfaces_count和 interfaces[interfaces_count]表示接口數量以及具體的每一個接口

(10)fields_count 和 field_info


fields_count:1 (0001)

field_info:0002 0004 0005 0000

access_flag name_index descriptor_index attribute_count
0002 0004 0005 0000
--- name Ljava/lang/String; 0

(11)methods_count 和 method_info:


access_flag name_index descriptor_index attribute_count attribute_info
0001 0006 0007 0001 ---
--- <init> ()V 1 ---

接下來是attribute_info
0008對應的常量池中的常量爲Code,表示的方法的Code屬性,所以到這裏大家應該明白方法的那些代碼是存儲在Class文件方法表中的屬性表中的Code屬性中。接下來我們在分析一下Code屬性,Code屬性的結構如下


attribute_name_index attribute_length max_stack max_locals code_length code[code_length]
0008 0000001D 0001 0001 00000005 2AB70001B1
exception_table_length attribute_count attribute_info
0000 0001 ---

0009,它表示常量池中屬性的名稱,查看常量池得知第9個常量的值爲 LineNumberTable,LineNumberTable用於描述java源代碼的行號和字節碼行號的對應關係,它不是運行時必需的屬性,如果通 過-g:none的編譯器參數來取消生成這項信息的話,最大的影響就是異常發生的時候,堆棧中不能顯示出出錯的行號,調試的時候也不能按照源代碼來設置斷點,接下來我們再看一下LineNumberTable的結構如下圖所示:


attribute_name_index attribute_length 字節流
0009 00000006 0001(有1個行號表) 0000(字節碼行號0) 0003(源碼行號3)

Class文件的屬性

屬性數量:0001

attribute_name_index attribute_length sourcefile_index
000A 00000002 000B
SourceFile 00000002 Test.java
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章