Android zygote啟動(dòng)流程詳解
對(duì)zygote的理解
在Android系統(tǒng)中,zygote是一個(gè)native進(jìn)程,是所有應(yīng)用進(jìn)程的父進(jìn)程。而zygote則是Linux系統(tǒng)用戶空間的第一個(gè)進(jìn)程——init進(jìn)程,通過fork的方式創(chuàng)建并啟動(dòng)的。
作用
zygote進(jìn)程在啟動(dòng)時(shí),會(huì)創(chuàng)建一個(gè)Dalvik虛擬機(jī)實(shí)例,每次孵化新的應(yīng)用進(jìn)程時(shí),都會(huì)將這個(gè)Dalvik虛擬機(jī)實(shí)例復(fù)制到新的應(yīng)用程序進(jìn)程里面,從而使得每個(gè)應(yīng)用程序進(jìn)程都有一個(gè)獨(dú)立的Dalvik虛擬機(jī)實(shí)例。
zygote進(jìn)程的主要作用有兩個(gè):
啟動(dòng)SystemServer。
孵化應(yīng)用進(jìn)程。
啟動(dòng)流程
啟動(dòng)入口
Zygote進(jìn)程在init進(jìn)程中,通過解析init.zygote.rc配置文件,以service(服務(wù))的方式啟動(dòng)并創(chuàng)建的。
以init.zygote32.rc為例來看下:
腳本講解
// system\core\rootdir\init.zygote32.rc service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system socket usap_pool_primary stream 660 root system onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond writepid /dev/cpuset/foreground/tasks
這段腳本要求 init 進(jìn)程創(chuàng)建一個(gè)名為 zygote 的進(jìn)程,該進(jìn)程要執(zhí)行的程序是“/system/bin/app_process”。并且為 zygote 進(jìn)程創(chuàng)建一個(gè) socket 資源 (用于進(jìn)程間通信,ActivityManagerService 就是通過該 socket 請(qǐng)求 zygote 進(jìn)程 fork 一個(gè)應(yīng)用程序進(jìn)程)。
后面的**--zygote**是參數(shù),表示啟動(dòng)的是zygote進(jìn)程。在app_process的main函數(shù)中會(huì)依據(jù)該參數(shù)決定執(zhí)行ZygoteInit還是Java類。
啟動(dòng)過程
zygote要執(zhí)行的程序便是system/bin/app_process,它的源代碼在frameworks/base/cmds/app_process/app_main.cpp
App_main::main
int main(int argc, char* const argv[])
{
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {//是否有--zygote參數(shù)。這個(gè)是啟動(dòng)zygote進(jìn)程的時(shí)候的參數(shù)
zygote = true;
//進(jìn)程名稱,設(shè)置為zygote
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {//是否有--start-system-server
startSystemServer = true;
....
if (zygote) {
//最最重要方法。。。如果是zygote進(jìn)程,則啟動(dòng)ZygoteInit。
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
AndroidRuntime::start
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JNIEnv* env;
//重點(diǎn)方法 創(chuàng)建VM虛擬機(jī),參數(shù)是指針,可以用于獲取返回的值,可以使用env來和Java層來做交互
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
//重點(diǎn)方法 給虛擬機(jī)注冊(cè)一些JNI函數(shù),(系統(tǒng)so庫(kù)、用戶自定義so庫(kù) 、加載函數(shù)等。)
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//找到類的main方法,并調(diào)用。如果是zygote的話,這里就會(huì)啟動(dòng)ZygoteInit類的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//調(diào)用main方法。這里通過JNI調(diào)用Java方法之后,Zygote(Native層)就進(jìn)入了Java的世界,從而開啟了Android中Java的世界。
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
App_main.main
AndroidRuntime.start
startVm//創(chuàng)建虛擬機(jī)
startReg//注冊(cè)JNI函數(shù)
ZygoteInit.main//這里就進(jìn)入到了Java層了
registerZygoteSocket//建立IPC的通訊機(jī)制
preload//預(yù)加載類和資源
startSystemServer//啟動(dòng)system_server
runSelectLoop//等待進(jìn)程創(chuàng)建的請(qǐng)求
對(duì)應(yīng)的源碼地址: /frameworks/base/cmds/app_process/App_main.cpp (內(nèi)含AppRuntime類) /frameworks/base/core/jni/AndroidRuntime.cpp /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java /frameworks/base/core/java/com/android/internal/os/Zygote.java /frameworks/base/core/java/android/net/LocalServerSocket.java
Zygote進(jìn)程的啟動(dòng)過程中,除了會(huì)創(chuàng)建一個(gè)Dalvik虛擬機(jī)實(shí)例之外,還會(huì)將Java運(yùn)行時(shí)庫(kù)加載到進(jìn)程中,以及注冊(cè)一些Android核心類的JNI方法到創(chuàng)建的Dalvik虛擬機(jī)實(shí)例中。
zygote進(jìn)程初始化時(shí)啟動(dòng)虛擬,并加載一些系統(tǒng)資源。這樣zygote fork出子進(jìn)程之后,子進(jìn)程也會(huì)繼承能正常工作的虛擬機(jī)和各種系統(tǒng)資源,剩下的只需要裝載APK文件的字節(jié)碼就可以運(yùn)行程序,。
Java應(yīng)用程序不能以本地進(jìn)程的形態(tài)運(yùn)行,必須在一個(gè)獨(dú)立的虛擬機(jī)中運(yùn)行。如果每次都重新啟動(dòng)虛擬機(jī),肯定就會(huì)拖慢應(yīng)用程序的啟動(dòng)速度。
注意:APK應(yīng)用程序進(jìn)程被zygote進(jìn)程孵化出來以后,不僅會(huì)獲得Dalvik虛擬機(jī)實(shí)例拷貝,還會(huì)與Zygote一起共享Java運(yùn)行時(shí)庫(kù)。
以上就是Android zygote啟動(dòng)流程詳解的詳細(xì)內(nèi)容,更多關(guān)于Android zygote啟動(dòng)流程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android使用SharedPreferences存儲(chǔ)XML文件的實(shí)現(xiàn)方法
這篇文章主要介紹了Android使用SharedPreferences存儲(chǔ)XML文件的實(shí)現(xiàn)方法,實(shí)例分析了SharedPreferences類的基本初始化與文件存儲(chǔ)相關(guān)技巧,需要的朋友可以參考下2016-07-07
android中ViewPager結(jié)合Fragment進(jìn)行無限滑動(dòng)
本篇文章中主要介紹了android中ViewPager結(jié)合Fragment進(jìn)行無限滑動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
橫豎屏切換導(dǎo)致頁面頻繁重啟screenLayout解析
這篇文章主要為大家介紹了橫豎屏切換導(dǎo)致頁面頻繁重啟screenLayout解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android 調(diào)用設(shè)備已有的相機(jī)應(yīng)用詳情
這篇文章主要介紹了Android 調(diào)用設(shè)備已有的相機(jī)應(yīng)用,如果我們只是需要讓用戶能夠拍攝照片,則可以直接請(qǐng)求已有相機(jī)應(yīng)用拍攝照片并將照片返回給我們,下面我們一起來看看這些功能,需要的朋友可以參考一下2021-10-10
Android 中build.prop 文件與 getprop 命令
這篇文章主要介紹了Android 中build.prop 文件與 getprop 命令的相關(guān)資料,需要的朋友可以參考下2017-06-06
Android 下載文件通知欄顯示進(jìn)度條功能的實(shí)例代碼
這篇文章主要介紹了Android 下載文件通知欄顯示進(jìn)度條功能的實(shí)例代碼,通過使用AsyncTask異步任務(wù)實(shí)現(xiàn),調(diào)用publishProgress()方法刷新進(jìn)度來實(shí)現(xiàn),具體代碼大家參考下本文2018-04-04

