Class文件規范
?根據《JAVA虛擬機規范》的規定,Class文件格式采用一種類似于C語言結構體的偽結構來存儲數據,這種偽結構中(Class文件格式中)只有兩種數據類型:“無符號數”和“表”。
?
?本篇文章圖中貼出的類型這一列也都是這兩個數據類型,如果類型是u開頭的表示為無符號數的數據類型,如果是_info結尾的表示是表類型。
?
- 無符號數就是正常的數字,以u1,u2,u4,u8來表示一個,兩個,四個,八個字節,通常用來描述數字,索引引用,數量值或者用來表達字符串值。
?u1在Class文件中為兩個數字或字母,比如00,01,0A,6F ; u2在Class文件中為四個數字或字母,比如0001,000A,6C61;
?
- 表是用來描述復合結構的數據,它由無符號數或者其他表構成,并在結尾處用“_info”表示。
?比如:cp_info為常量池表,field_info為字段表,method_info為方法表,attribute_info為屬性表。本篇文章會講解除了屬性表之外的其他表結構,屬性表單獨寫一篇文章進行講解
?
- 本質上Class結構也是將表和無符號數組合起來的一張表。
Class文件大結構總覽
后面講的所有結構都是按照這個Class文件表講的,所以這張圖先看下。
magic
Class文件的 「頭四個字節」 表示魔數,這個值存在于各個文件中,在之前的這篇文章里面講過這個字段:驗證apk文件的magic,magic是用來驗證是不是屬于某種結構的,即使用戶更改了文件的后綴名也沒事,通過這個字段就可以看出他是什么類型的文件。「因此每一種文件格式的魔數magic都不一樣,因為是用來表示其屬于哪種文件格式的。」
?Class文件的magic為0XCAFFBABE(咖啡寶貝)
?
Class文件版本號
接下來的兩個字節表達的Class文件的 「次版本號(Minor Version)」 ,再接著兩個字節表達的是 「主版本號(Major Version)」 。
?高版本的JDK能夠兼容低版本的Class文件,但是低版本的JDK不能運行高版本的Class文件(規范中Class文件校驗必須要求的!)
?
Constant_Pool常量池
1、Class文件中第一個出現的表結構的數據,主要存放兩種常量:「字面量和符號引用。」
?字面量:Java語言層面常量的概念。eg:字符串,被聲明為final的常量等
?
?符號引用:編譯原理方面的概念。eg:被模塊導出或者開放的包(Package) 類和接口的全限定名(也就是類所屬的包名和類的名字) 字段的名稱和描述符(名稱簡單理解就是字段名,描述符為字段所屬的類型) 方法的名稱和描述符(名稱簡單理解就是方法名,描述符為方法參數和返回值) 方法句柄和方法類型(Method Handle,Method Type,Invoke Dynamic) 動態調用點和動態常量
?
2、符號引用,由于Class文件是在編譯后生成的,因此運行的時候需要 「將符號引用轉換為對應數據在內存中的地址」 ,否則使用的時候會找不到真正的內存入口地址(也就是不能被虛擬機直接使用)。
?當虛擬機做類加載的時候,會從常量池中拿出對應的符號引用,在類創建或者運行時解析,翻譯到具體的內存地址之中 比如class文件的類名,當類被加載到虛擬機中時,需要將這個符號引用轉換為類真實所在的內存地址才能被正常訪問。
?
3.常量池中存儲的數據數量 「從1開始計數」 ,第0項常量空出來是因為有些數據并不需要引用常量池中的數據時,就可以用第0項常量來表達。
4.常量池的數據數量會在版本號之后用兩個字節來表達,之后才是常量池中的數據
?這樣做是因為沒有Class文件中 「沒有分隔符」 來表示一組數據結束,因此Class文件中的數據必須嚴格按照固定長度,固定數量去存放,不允許改變。
?
5.常量池中 「每一項常量數據都是一張表」 ,每個表結構中都有一個u1類型的標志位標識自己屬于哪種類型的表。
各個表對應的含義
這些表有著各自完全獨立的結構,之間沒有任何關聯。
反編譯代碼示例
C:\\>javap -verbose TestClass
Compiled from "TestClass.java"
public class org.fenixsoft.clazz.TestClass extends java.lang.Object SourceFile: "TestClass.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // org/fenixsoft/clazz/TestClass
const #2 = Asciz org/fenixsoft/clazz/TestClass;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz m;
const #6 = Asciz I;
const #7 = Asciz ;
const #8 = Asciz ()V;
const #9 = Asciz Code;
const #10 = Method #3.#11; // java/lang/Object."":()V
const #11 = NameAndType #7:#8;// "":()V
const #12 = Asciz LineNumberTable;
const #13 = Asciz LocalVariableTable;
const #14 = Asciz this;
const #15 = Asciz Lorg/fenixsoft/clazz/TestClass;;
const #16 = Asciz inc;
const #17 = Asciz ()I;
const #18 = Field #1.#19; // org/fenixsoft/clazz/TestClass.m:I
const #19 = NameAndType #5:#6; // m:I
const #20 = Asciz SourceFile;
const #21 = Asciz TestClass.java;
代碼塊中Asciz就是之前說的Constant_UTF8_info常量(也就是字符串常量),可以看到這些數據都是由這個常量來組成的,
常量池中常量表對應數據結構內容
第一列常量為之前 「各個表對應的含義」 中提到的表結構類型也就是表的名稱;
第二列中的項目為各個表中存放的不同的數據內容有哪些,這些表的數據中都有一個標識位tag用來標識不同的表,在之前 「各個表對應的含義」 中也提到過;
第三列為描述不同于之前講的表的描述,這列說明的是**「表中存儲的不同數據的描述」**
圖例:
-
JAVA
+關注
關注
20文章
2984瀏覽量
106855 -
C語言
+關注
關注
180文章
7630瀏覽量
140283 -
Class
+關注
關注
0文章
53瀏覽量
20018 -
存儲數據
+關注
關注
0文章
89瀏覽量
14284
發布評論請先 登錄
jvm的類加載器的整體結構及過程解析

Jvm的整體結構和特點
Jvm工作原理學習筆記
JVM入門之Class結構屬性表1

JVM入門之Class結構屬性表2

JVM入門之認識程序運行本質

評論