通過上一節Android init進程啟動的分析可知,init進程在啟動過程中,解析并處理了init.rc和init.hardware.rc兩個初始化腳本文件,在兩個初始化腳本文件里,定義了一系列的service section,這些service在boot觸發器下,通過class_start default依次啟動,其過程總結如下:
1. init 解析init.rc
2. init 將init.rc里的service放到隊列里面等待觸發器的觸發
3. init通過 action_for_each_trigger("boot", action_add_queue_tail);觸發boot Action
4. 依次執行boot下的Commands,包括class_start default命令
5. 所有的service默認的class為默認值:default,所以,所有init.rc中的service都被啟動
zygote服務啟動
通過init.rc中對zygote服務的描述可知,其對應的程序為:/system/bin/app_process
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
該服務會在on boot時觸發,其程序為/system/bin/app_process,服務名為zygote,-Xzygote /system/bin --zygote --start-system-server為參數列表。
在創建了zygote 服務后,在目錄下建立一個stream socket文件/dev/socket/zygote,權限為666,當zygote服務重啟時,重啟media服務
通過find ./ -name Android.mk -exec grep -l app_process {} \; 命令,查找到,它在./frameworks/base/cmds/app_process/目錄中被編譯,其主要入口文件為:
./frameworks/base/cmds/app_process/app_main.cpp
找到該程序的main入口函數,
int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i< argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char *arg;
const char *argv0;
argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
// 在zygote服務的參數列表中,以'--和非'-'開頭的參數,是dalvik的參數:/system/bin--zygote --start-system-server,交給Vm來處理
int i = runtime.addVmArguments(argc, argv);
// 找到zygote的目錄:/system/bin
if (i < argc) {
runtime.mParentDir = argv[i++];
}
// 如果接下來的參數是:--zygote --start-system-server的話,設置argv0="zygote",startSystemServer= true,啟動java VM
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
&nbnbsp; }
}
根據service zygote的參數,啟動VM:
runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);
runtime是AppRuntime的對象,AppRuntime是AndroidRuntime的子類:

runtime.start方法在AndroidRuntime里實現:
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n"); //logcat里顯眼的字樣
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
blockSigpipe();
/*
* 'startSystemServer == true' means runtime is obslete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
if (startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
const char* rootDir = getenv("ANDROID_ROOT"); // 取得Android的根目錄:/system
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
goto bail;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
// 啟動Dalvik虛擬機,在AndroidRuntime::startVm方法中,設備了大量VM的參數,后調用JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs),通過JNI啟動虛擬機
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* Register android functions.
*/
if (startReg(env) < 0) { // 注冊系統使用的JNI函數
LOGE("Unable to register all android natives\n");
goto bail;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
stringClass = env->FindClass("java/lang/String"); // 從Dalvik虛擬機里,查找到String類,
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL); // 創建一個String數組,有兩個元素(strArray = new String[2])
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className); // 創建一個Java String對象,初始值為:className,其實是start第一個參數:com.android.internal.os.ZygoteInit
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr); // 設置strArray 第一個元素的值為:classNameStr (strArray[0] =classNameStr)
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false"); // 創建一個Java String對象,初始值為:startSystemServer ,其實是start第二個參數:true
env->SetObjectArrayElement(strArray, 1, startSystemServerStr); // 設置strArray 第二個元素的值為:strArray[1] =startSystemServerStr
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
// 根據上面的解釋可知:準備啟動Java VM,并且創建VM的主線程,只要VM不退出,這個主線程一直運行。
jclass startClass;
jmethodID startMeth;
for (cp = slashClassName; *cp != '\0'; cp++) //
將com.android.internal.os.ZygoteInit中的包分隔符'.'換成'/'即:com/android/internal/os/ZygoteInit
if (*cp == '.')
*cp = '/';
startClass = env->FindClass(slashClassName); // 從VM中查找ZygoteInit類,難道它要在VM里加載這個類。。。。
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); //
查找到com/android/internal/os/ZygoteInit類中的main方法ID,接合Java文件命名規則,你能更深刻的理解,為什么主類名要和文件名一致,并且main方法為static方法。
if (startMeth == NULL) {
LOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray); // 調用ZygoteInit類里的main方法,這不是運行ZygoteInit這個JAVA程序嗎!!
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
bail:
free(slashClassName);
}
由上面的分析可知,AndroidRuntime::start方法實現了下面功能:
1> 通過startVm來啟動虛擬機,并且注冊了一些系統JNI函數,由于這個時候VM里還沒有程序,只是個空的VM執行環境
2> 通過AndroidRuntime::start的參數,在JNI代碼里構建第一個Java程序ZygoteInit,將其作為VM的主線程,同時給其傳遞兩個JNI構建的參數:
"com/android/internal/os/ZygoteInit"和"true"
總結:
Android系統的啟動是由init進程加載并啟動了里面的/system/bin/app_process程序作為zygote服務,然后在zygote服務里執行runtime.start啟動Dalvik虛擬機,加載了ZygoteInit類作為Dalvik虛擬機的第一個主線程。至此,Android的Java運行環境就準備完畢了。