一. class文件結構深入解析(生成&執行&內部結構)
1. 如何生成一個class文件?
class文件是能夠被JVM識別,加載並執行的文件格式。說白了,它就是一種文件格式,就像mp4、jpg、txt等文件格式一樣。
只有java源代碼能編譯成class文件嗎?
下圖幾種語言也能編譯成class文件。
2. 如何生成一個class文件?
一般來說,有兩種方式生成class文件:
- IDE會自動幫我們build出class文件
- 手動通過javac去生成class文件(IDE也是通過javac生成的)
3. class文件的作用
記錄一個類文件的所有信息。
4. class文件格式詳解(重點)
- 一種8位字節的二進制流文件(與音視頻文件一樣)
- 各個數據按順序緊密的排列,無間隙(不像有些文件,爲了讀取上的方便,會做一些填充,比如每80字節是一行)
- 每個類、枚舉、接口都單獨佔據一個class文件
下面我們來講解一下class文件結構
我們逐行來講解每個字段的作用。
- magic字段。它是無符號4字節類型。它的作用是一個摘要段,好比文件的md5加密,用來判斷class文件是否有被篡改。
- minor_version字段。它指明class文件最早可以支持的jdk版本。
- major_version字段。表示當前class文件是由那個jdk版本生成的。
- constant_pool_count字段。表示class文件中常量池的數量,通常來說,只有一個常量池。
constant_pool字段[核心]。這個字段代表真正的常量池,它是cp_info類型。也就是說,是一個結構體類型。constant_pool的取值範圍如下:
CONSTANT_Integer_info:int類型
CONSTANT_Long_info:long類型
CONSTANT_String_info:String類型
CONSTANT_Class_info:類相關信息
CONSTANT_Fieldref_info:類中成員變量相關信息
CONSTANT_Methodref_info:類中方法相關信息access_flag字段。表示class文件的作用域,比如public,private等。如下圖,access_flags可以取如下值。
- this_class字段。在java源文件中沒有定義this關鍵字,而jdk在生成class文件時補充了這個字段。
- super_class字段。跟this_class原理類似。
- interfaces_count字段。表明當前class文件實現了多少個接口,且只會記錄直接實現的接口數量。
- interfaces字段。表明當前class文件直接實現的接口數量。
- fields_count字段。表明當前class文件所有成員變量個數。
- fields字段。是field_info類型。表明成員變量類型、名稱等。記錄當前class文件所有成員變量。
- methods_count字段。
- methods字段。
- attribute_count字段。屬性個數。
- attributes字段。
5. class文件弊端
- 內存佔用大,不適合移動端
- 堆棧的加棧模式,加載速度慢
- 文件IO操作多,類查找慢
二. dex文件結構深入解析(生成&執行&內部結構)
1. 什麼是dex文件?
能夠被DVM識別,加載並執行的文件格式
2. 如何生成一個dex文件?
- 通過IDE自動build生成
- 手動通過dx命令生成dex文件
那麼,如何用dx命令生成dex文件,並在手機上運行呢?
- 找到 sdk目錄/build-tools/sdk版本,如我的路徑:
/Users/colinambitious/Library/Android/sdk/build-tools/26.0.22.
在此文件夾下可以找到dx文件,將此目錄設爲環境變量。 寫一個Test.java文件
public class Test{ public static void main(String args[]){ System.out.println("Hello World."); } }
使用以下命令,編譯成class文件:
javac -target 1.6 -source 1.6 Test.java- 使用adb命令,將生成的class文件push到手機上
adb push Test.dex /storage/emulated/0 - 使用adb shell命令,遠程連接到手機
adb shell - 運行該dex文件
dalvikvm -cp ./Test.dex Test
3. dex文件的作用
記錄整個工程中所有類文件的信息,
4. dex文件格式詳解(重點)
- 一種8字節的二進制流文件
- 各個數據按順序緊密排列,無間隙
- 整個應用所有java源文件都在一個dex中
我們來結合下面這張圖來講解。
dex文件總共有三個部分:文件頭、索引區、數據區。
- 文件頭header。主要記錄了dex文件信息。
- 索引區。包含了字符串索引、類型索引、方法原型索引、域索引、方法索引。
- 數據區。包含了索引區索引的內容。
三. class文件與dex文件對比
- 本質上class文件和dex文件都是一樣的(java源文件演變而來),而dex文件又是從class文件演變而來的。
- class文件存在許多冗餘信息,dex去除冗餘。因爲,class文件一個類就有一個常量池,dex文件中所有數據都是存儲在同一個數據區的。
從下面這張圖可以看出,jar包中每一個class都有header、constant pool等,而dex把這些所有class的信息整合到了一起。