【Android熱修復與插件化 二】class&dex文件詳解

一. 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文件,並在手機上運行呢?

  1. 找到 sdk目錄/build-tools/sdk版本,如我的路徑:
    /Users/colinambitious/Library/Android/sdk/build-tools/26.0.22.
    在此文件夾下可以找到dx文件,將此目錄設爲環境變量。
  2. 寫一個Test.java文件

    public class Test{
    public static void main(String args[]){
        System.out.println("Hello World.");
    }
    }
  3. 使用以下命令,編譯成class文件:
    javac -target 1.6 -source 1.6 Test.java

  4. 使用adb命令,將生成的class文件push到手機上
    adb push Test.dex /storage/emulated/0
  5. 使用adb shell命令,遠程連接到手機
    adb shell
  6. 運行該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的信息整合到了一起。
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章