1. 程式人生 > >Android 啟動載入jar包 init.rc BOOTCLASSPATH

Android 啟動載入jar包 init.rc BOOTCLASSPATH

一直在研究 Dalvik 的實現,今天突然想起一件事情,我們預設可以用 java.lang.Object 等系統類,他是在什麼時候被載入進來了呢,我們自己的類是否可以這樣預先載入進去呢?

順著這個思路,再回顧一下原來對 Zygote 啟動時的流程,探索一番!

Zygote 啟動流程(網上有很多的分析不太詳訴):

>>>  Kernel 啟動

>>>  啟動 init 程式,此程式解析 init.rc 進行執行

>>>  在 init.rc 中有啟動 zygote 程式碼

>>>  zygote 啟動後最後 fork 出 system_server 進行系統服務

>>>  zygote 等待 socket 事件準備孵化使用者程序

在 Zygote 的啟動中有如下關鍵呼叫:

AppRuntime.start 啟動 com.android.internal.os.ZygoteInit 類處理

既然這時能夠呼叫 java 類處理了,哪麼系統基礎類肯定在這之前準備好了,順著這個向裡面看

AppRuntime 繼承 AndroidRuntime

AndroidRuntime 的 start 函式,呼叫了 JNI_CreateJavaVM 函式生成虛擬機器

JNI_CreateJavaVM 是 jni.c 中,也就是 libdvm.so 中的一個函式

JNI_CreateJavaVM 中呼叫了 dvmStartup 函式啟動一個虛擬機器

dvmStartup 呼叫了setCommandLineDefaults 實現引數預設值。裡面有最為重要的獲取環境變理 BOOTCLASSPATH 方法。

回頭看一下 init.rc 中

[java] view plaincopyprint?
  1. export BOOTCLASSPATH /system/framework/core.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/core-junit.jar  


原來是在這裡指定了一些基礎類的 jar 包

繼續看程式碼

dvmStartup 中呼叫了 setCommandLineDefaults 設定預設  BOOTCLASSPATH

dvmStartup 中呼叫了dvmClassStartup 載入預設啟動類

dvmClassStartup 中呼叫了 processClassPath 處理類路徑,其實就是 BOOTCLASSPATH 中的值。

processClassPath 中建立結構體 ClassPathEntry 來儲存一個路徑資訊

processClassPath 中呼叫了 prepareCpe 準備類路徑節點

prepareCpe 中呼叫了dvmJarFileOpen 開啟一個 jar 包

所有被載入的 Jar 包類都放到全域性對像 gDvm.bootClassPath 中儲存。

gDvm.bootClassPath 對像的結尾都是用一個特殊的結構體來表示的,這裡是 kind = kCpeLastEntry 表示是最後一個類路徑節點,因些不用另外一個變量表示大小。

大概清楚了!

-------------------------------------- 無聊的分割線 --------------------------------------

哪麼我們想增加一個基礎包給系統使用,大概有幾種方法:

  1. 改 init.rc 的 BOOTCLASSPATH 環境變數初始值
  2. 在 zygote 啟動前改動 BOOTCLASSPATH 環境變數
  3. 在 zygote 啟動後想辦法讓他載入一個 jar 包

到此發現,系統啟動前後環環相扣,並助實現的都是可擴充套件化,輕易不硬編碼到程式碼中。

以後會繼續深入研究一下其它東西的載入,比如:很有意思的一個 apk (ramework-res.apk)  這個包是系統面板實現的一個包