在Android中存在着C和Java兩個徹底不一樣的世界,前者直接創建在Linux的基礎上,後者直接創建在JVM的基礎上。zygote的中文名字爲「受精卵」,這個名字很好的詮釋了zygote進程的做用。做爲java世界的孵化者,zygote自己是一個native程序,是由init根據init.rc文件中的配置項建立的。php
@/system/core/rootdir/init.rchtml
- service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
- class main
- socket zygote stream 660 root system
- onrestart write /sys/android_power/request_state wake
- onrestart write /sys/power/state on
- onrestart restart media
- onrestart restart netd
關於init是如何解析和建立zygote進程的,這裏再也不贅述,不明的同窗能夠參考init進程【2】——解析配置文件一文。這裏解析一下上面的第一行:service是rc腳本中的一種SECTION,zygote表示service的名字,/system/bin/app_process表示service的路徑,-Xzygote /system/bin --zygote --start-system-server則表示傳入的參數。java
zygote的實如今app_main.cpp中:linux
@frameworks/base/cmds/app_process/app_main.cppandroid
- int main(int argc, char* const argv[])
- {
- #ifdef __arm__
-
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", value, "");
- bool is_qemu = (strcmp(value, "1") == 0);
- if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
- int current = personality(0xFFFFFFFF);
- if ((current & ADDR_COMPAT_LAYOUT) == 0) {
- personality(current | ADDR_COMPAT_LAYOUT);
- setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
- execv("/system/bin/app_process", argv);
- return -1;
- }
- }
- unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
- #endif
-
-
- mArgC = argc;
- mArgV = argv;
-
- mArgLen = 0;
- for (int i=0; i<argc; i++) {
- mArgLen += strlen(argv[i]) + 1;
- }
- mArgLen--;
-
- AppRuntime runtime;
- const char* argv0 = argv[0];
-
-
-
- argc--;
- argv++;
-
-
-
- int i = runtime.addVmArguments(argc, argv);
-
-
- bool zygote = false;
- bool startSystemServer = false;
- bool application = false;
- const char* parentDir = NULL;
- const char* niceName = NULL;
- const char* className = NULL;
- while (i < argc) {
- const char* arg = argv[i++];
- if (!parentDir) {
- parentDir = arg;
- } else if (strcmp(arg, "--zygote") == 0) {
- zygote = true;
- niceName = "zygote";
- } else if (strcmp(arg, "--start-system-server") == 0) {
- startSystemServer = true;
- } else if (strcmp(arg, "--application") == 0) {
- application = true;
- } else if (strncmp(arg, "--nice-name=", 12) == 0) {
- niceName = arg + 12;
- } else {
- className = arg;
- break;
- }
- }
-
- if (niceName && *niceName) {
- setArgv0(argv0, niceName);
- set_process_name(niceName);
- }
-
- runtime.mParentDir = parentDir;
-
- if (zygote) {
- runtime.start("com.android.internal.os.ZygoteInit",
- startSystemServer ? "start-system-server" : "");
- } else if (className) {
-
- runtime.mClassName = className;
- runtime.mArgC = argc - i;
- runtime.mArgV = argv + i;
- runtime.start("com.android.internal.os.RuntimeInit",
- application ? "application" : "tool");
- } else {
- fprintf(stderr, "Error: no class name or --zygote supplied.\n");
- app_usage();
- LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
- return 10;
- }
- }
經過對main()函數的分析,能夠看出main()主要根據傳入的參數初始化啓動參數,具體的啓動過程是由AppRuntime完成的。AppRuntime的聲明和實現都在app_main.cpp中,它繼承自AndroidRuntime,AppRuntime的實現以下:git
能夠看出start是AndroidRuntime中的方法。經過start函數前面的註釋咱們瞭解到它的主要做用是:啓動Android運行時環境,包括啓動虛擬機和調用className參數所指定的類的main()方法(即:Java中的main方法)。
- void AndroidRuntime::start(const char* className, const char* options)
- {
- ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
- className != NULL ? className : "(unknown)");
-
-
- if (strcmp(options, "start-system-server") == 0) {
-
- 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");
- if (rootDir == NULL) {
- rootDir = "/system";
- if (!hasDir("/system")) {
- LOG_FATAL("No root directory specified, and /android does not exist.");
- return;
- }
- setenv("ANDROID_ROOT", rootDir, 1);
- }
-
-
-
-
-
- JniInvocation jni_invocation;
- jni_invocation.Init(NULL);
- JNIEnv* env;
- if (startVm(&mJavaVM, &env) != 0) {
- return;
- }
- onVmCreated(env);
-
-
- if (startReg(env) < 0) {
- ALOGE("Unable to register all android natives\n");
- return;
- }
-
-
- jclass stringClass;
- jobjectArray strArray;
- jstring classNameStr;
- jstring optionsStr;
-
- stringClass = env->FindClass("java/lang/String");
- assert(stringClass != NULL);
-
- strArray = env->NewObjectArray(2, stringClass, NULL);
- assert(strArray != NULL);
- classNameStr = env->NewStringUTF(className);
- assert(classNameStr != NULL);
- env->SetObjectArrayElement(strArray, 0, classNameStr);
- optionsStr = env->NewStringUTF(options);
- env->SetObjectArrayElement(strArray, 1, optionsStr);
-
-
- char* slashClassName = toSlashClassName(className);
- jclass startClass = env->FindClass(slashClassName);
- if (startClass == NULL) {
- ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
-
- } else {
- jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
- "([Ljava/lang/String;)V");
- if (startMeth == NULL) {
- ALOGE("JavaVM unable to find main() in '%s'\n", className);
-
- } else {
- env->CallStaticVoidMethod(startClass, startMeth, strArray);
-
- #if 0
- if (env->ExceptionCheck())
- threadExitUncaughtException(env);
- #endif
- }
- }
- free(slashClassName);
-
-
- ALOGD("Shutting down VM\n");
- if (mJavaVM->DetachCurrentThread() != JNI_OK)
- ALOGW("Warning: unable to detach main thread\n");
- if (mJavaVM->DestroyJavaVM() != 0)
- ALOGW("Warning: VM did not shut down cleanly\n");
- }
經過上面對start()函數的分析能夠發現,在start()中主要完成了以下三項工做:
- 啓動JVM。
- 註冊Android JNI函數。
- 調用ZygoteInit的main()方法。
建立Java虛擬機
start()中與建立虛擬機相關的代碼以下:
- JniInvocation jni_invocation;
- jni_invocation.Init(NULL);
- JNIEnv* env;
- if (startVm(&mJavaVM, &env) != 0) {
- return;
- }
- onVmCreated(env);
這裏代碼中
建立一個JniInvocation實例,而且調用它的成員函數init來初始化JNI環境:
@/libnativehelper/jniInvocation.cpp
- bool JniInvocation::Init(const char* library) {
- #ifdef HAVE_ANDROID_OS
- char default_library[PROPERTY_VALUE_MAX];
- property_get("persist.sys.dalvik.vm.lib", default_library, "libdvm.so");
- #else
- const char* default_library = "libdvm.so";
- #endif
- if (library == NULL) {
- library = default_library;
- }
-
- handle_ = dlopen(library, RTLD_NOW);
- if (handle_ == NULL) {
- ALOGE("Failed to dlopen %s: %s", library, dlerror());
- return false;
- }
- if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
- "JNI_GetDefaultJavaVMInitArgs")) {
- return false;
- }
- if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
- "JNI_CreateJavaVM")) {
- return false;
- }
- if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
- "JNI_GetCreatedJavaVMs")) {
- return false;
- }
- return true;
- }
JniInvocation類的成員函數init所作的事情很簡單。它首先是讀取系統屬性persist.sys.dalvik.vm.lib的值。系統屬性persist.sys.dalvik.vm.lib的值要麼等於libdvm.so,要麼等於libart.so,這兩個so庫分別對應着Dalvik虛擬機和ART虛擬機環境。
在初始化完虛擬機環境後,接下來調用startVm()來建立虛擬機。
@/frameworks/base/core/jni/AndroidRuntime.cpp
- int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
- {
- int result = -1;
- JavaVMInitArgs initArgs;
- JavaVMOption opt;
- char propBuf[PROPERTY_VALUE_MAX];
- char stackTraceFileBuf[PROPERTY_VALUE_MAX];
- char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
- char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
- char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
- char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
- char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
- char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
- char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
- char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
- char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
- char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
- char extraOptsBuf[PROPERTY_VALUE_MAX];
- char* stackTraceFile = NULL;
- bool checkJni = false;
- bool checkDexSum = false;
- bool logStdio = false;
- enum {
- kEMDefault,
- kEMIntPortable,
- kEMIntFast,
- kEMJitCompiler,
- } executionMode = kEMDefault;
-
-
- property_get("dalvik.vm.checkjni", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- checkJni = true;
- } else if (strcmp(propBuf, "false") != 0) {
-
- property_get("ro.kernel.android.checkjni", propBuf, "");
- if (propBuf[0] == '1') {
- checkJni = true;
- }
- }
-
- property_get("dalvik.vm.execution-mode", propBuf, "");
- if (strcmp(propBuf, "int:portable") == 0) {
- executionMode = kEMIntPortable;
- } else if (strcmp(propBuf, "int:fast") == 0) {
- executionMode = kEMIntFast;
- } else if (strcmp(propBuf, "int:jit") == 0) {
- executionMode = kEMJitCompiler;
- }
-
- property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");
-
- property_get("dalvik.vm.check-dex-sum", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- checkDexSum = true;
- }
-
- property_get("log.redirect-stdio", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- logStdio = true;
- }
-
- strcpy(enableAssertBuf, "-ea:");
- property_get("dalvik.vm.enableassertions", enableAssertBuf+4, "");
-
- strcpy(jniOptsBuf, "-Xjniopts:");
- property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");
-
-
- opt.extraInfo = (void*) runtime_exit;
- opt.optionString = "exit";
- mOptions.add(opt);
-
-
- opt.extraInfo = (void*) runtime_vfprintf;
- opt.optionString = "vfprintf";
- mOptions.add(opt);
-
-
- opt.extraInfo = (void*) runtime_isSensitiveThread;
- opt.optionString = "sensitiveThread";
- mOptions.add(opt);
-
- opt.extraInfo = NULL;
-
-
-
- opt.optionString = "-verbose:gc";
- mOptions.add(opt);
-
-
-
- strcpy(heapstartsizeOptsBuf, "-Xms");
- property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");
- opt.optionString = heapstartsizeOptsBuf;
- mOptions.add(opt);
- strcpy(heapsizeOptsBuf, "-Xmx");
- property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
- opt.optionString = heapsizeOptsBuf;
- mOptions.add(opt);
-
-
- opt.optionString = "-XX:mainThreadStackSize=24K";
- mOptions.add(opt);
-
-
- strcpy(jitcodecachesizeOptsBuf, "-Xjitcodecachesize:");
- property_get("dalvik.vm.jit.codecachesize", jitcodecachesizeOptsBuf+19, NULL);
- if (jitcodecachesizeOptsBuf[19] != '\0') {
- opt.optionString = jitcodecachesizeOptsBuf;
- mOptions.add(opt);
- }
-
- strcpy(heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
- property_get("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf+20, "");
- if (heapgrowthlimitOptsBuf[20] != '\0') {
- opt.optionString = heapgrowthlimitOptsBuf;
- mOptions.add(opt);
- }
-
- strcpy(heapminfreeOptsBuf, "-XX:HeapMinFree=");
- property_get("dalvik.vm.heapminfree", heapminfreeOptsBuf+16, "");
- if (heapminfreeOptsBuf[16] != '\0') {
- opt.optionString = heapminfreeOptsBuf;
- mOptions.add(opt);
- }
-
- strcpy(heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
- property_get("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf+16, "");
- if (heapmaxfreeOptsBuf[16] != '\0') {
- opt.optionString = heapmaxfreeOptsBuf;
- mOptions.add(opt);
- }
-
- strcpy(heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
- property_get("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf+26, "");
- if (heaptargetutilizationOptsBuf[26] != '\0') {
- opt.optionString = heaptargetutilizationOptsBuf;
- mOptions.add(opt);
- }
-
- property_get("ro.config.low_ram", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- opt.optionString = "-XX:LowMemoryMode";
- mOptions.add(opt);
- }
-
-
- property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");
- if (dexoptFlagsBuf[0] != '\0') {
- const char* opc;
- const char* val;
-
- opc = strstr(dexoptFlagsBuf, "v=");
- if (opc != NULL) {
- switch (*(opc+2)) {
- case 'n': val = "-Xverify:none"; break;
- case 'r': val = "-Xverify:remote"; break;
- case 'a': val = "-Xverify:all"; break;
- default: val = NULL; break;
- }
-
- if (val != NULL) {
- opt.optionString = val;
- mOptions.add(opt);
- }
- }
-
- opc = strstr(dexoptFlagsBuf, "o=");
- if (opc != NULL) {
- switch (*(opc+2)) {
- case 'n': val = "-Xdexopt:none"; break;
- case 'v': val = "-Xdexopt:verified"; break;
- case 'a': val = "-Xdexopt:all"; break;
- case 'f': val = "-Xdexopt:full"; break;
- default: val = NULL; break;
- }
-
- if (val != NULL) {
- opt.optionString = val;
- mOptions.add(opt);
- }
- }
-
- opc = strstr(dexoptFlagsBuf, "m=y");
- if (opc != NULL) {
- opt.optionString = "-Xgenregmap";
- mOptions.add(opt);
-
-
- opt.optionString = "-Xgc:precise";
- mOptions.add(opt);
- }
- }
-
-
-
- opt.optionString =
- "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
- mOptions.add(opt);
-
- ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
- if (checkJni) {
-
- opt.optionString = "-Xcheck:jni";
- mOptions.add(opt);
-
-
- opt.optionString = "-Xjnigreflimit:2000";
- mOptions.add(opt);
-
-
-
-
- }
-
- char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
- property_get("dalvik.vm.lockprof.threshold", propBuf, "");
- if (strlen(propBuf) > 0) {
- strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
- strcat(lockProfThresholdBuf, propBuf);
- opt.optionString = lockProfThresholdBuf;
- mOptions.add(opt);
- }
-
-
- char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
- property_get("dalvik.vm.jit.op", propBuf, "");
- if (strlen(propBuf) > 0) {
- strcpy(jitOpBuf, "-Xjitop:");
- strcat(jitOpBuf, propBuf);
- opt.optionString = jitOpBuf;
- mOptions.add(opt);
- }
-
-
- char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
- property_get("dalvik.vm.jit.method", propBuf, "");
- if (strlen(propBuf) > 0) {
- strcpy(jitMethodBuf, "-Xjitmethod:");
- strcat(jitMethodBuf, propBuf);
- opt.optionString = jitMethodBuf;
- mOptions.add(opt);
- }
-
- if (executionMode == kEMIntPortable) {
- opt.optionString = "-Xint:portable";
- mOptions.add(opt);
- } else if (executionMode == kEMIntFast) {
- opt.optionString = "-Xint:fast";
- mOptions.add(opt);
- } else if (executionMode == kEMJitCompiler) {
- opt.optionString = "-Xint:jit";
- mOptions.add(opt);
- }
-
- if (checkDexSum) {
-
- opt.optionString = "-Xcheckdexsum";
- mOptions.add(opt);
- }
-
- if (logStdio) {
-
- opt.optionString = "-Xlog-stdio";
- mOptions.add(opt);
- }
-
- if (enableAssertBuf[4] != '\0') {
-
- if (strcmp(enableAssertBuf+4, "all") == 0)
- enableAssertBuf[3] = '\0';
- ALOGI("Assertions enabled: '%s'\n", enableAssertBuf);
- opt.optionString = enableAssertBuf;
- mOptions.add(opt);
- } else {
- ALOGV("Assertions disabled\n");
- }
-
- if (jniOptsBuf[10] != '\0') {
- ALOGI("JNI options: '%s'\n", jniOptsBuf);
- opt.optionString = jniOptsBuf;
- mOptions.add(opt);
- }
-
- if (stackTraceFileBuf[0] != '\0') {
- static const char* stfOptName = "-Xstacktracefile:";
-
- stackTraceFile = (char*) malloc(strlen(stfOptName) +
- strlen(stackTraceFileBuf) +1);
- strcpy(stackTraceFile, stfOptName);
- strcat(stackTraceFile, stackTraceFileBuf);
- opt.optionString = stackTraceFile;
- mOptions.add(opt);
- }
-
-
- property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
- parseExtraOpts(extraOptsBuf);
-
-
- {
- char langOption[sizeof("-Duser.language=") + 3];
- char regionOption[sizeof("-Duser.region=") + 3];
- strcpy(langOption, "-Duser.language=");
- strcpy(regionOption, "-Duser.region=");
- readLocale(langOption, regionOption);
- opt.extraInfo = NULL;
- opt.optionString = langOption;
- mOptions.add(opt);
- opt.optionString = regionOption;
- mOptions.add(opt);
- }
-
-
- opt.optionString = "-Djava.io.tmpdir=/sdcard";
- mOptions.add(opt);
-
- initArgs.version = JNI_VERSION_1_4;
- initArgs.options = mOptions.editArray();
- initArgs.nOptions = mOptions.size();
- initArgs.ignoreUnrecognized = JNI_FALSE;
-
-
- if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
- ALOGE("JNI_CreateJavaVM failed\n");
- goto bail;
- }
-
- result = 0;
-
- bail:
- free(stackTraceFile);
- return result;
- }
能夠看出這個函數的絕大部分都是在設置Java虛擬機的各項參數,沒有什麼好說。看到下面這一段變量定義,不知道你們有沒有去思考過,這裏爲何用PROPERTY_VALUE_MAX做爲初始大小?
- char propBuf[PROPERTY_VALUE_MAX];
- char stackTraceFileBuf[PROPERTY_VALUE_MAX];
- char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
- char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
- char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
- char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
- char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
- char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
- char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
- char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
- char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
- char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
下面是
PROPERTY_VALUE_MAX的定義:
@system/core/include/cutils/properties.h
- #define PROPERTY_KEY_MAX PROP_NAME_MAX
- #define PROPERTY_VALUE_MAX PROP_VALUE_MAX
因此,沒錯,
PROPERTY_VALUE_MAX是Android中屬性value的最大長度,而java虛擬機的這些參數都是經過Android屬性賦值和控制的,因此他們的值得大小確定不能超過屬性的最大長度。下面是個人小米2S手機中的一部分Java參數。Android中全部屬性均可以經過getprop命令來查看。
- [dalvik.vm.heapconcurrentstart]: [2097152]
- [dalvik.vm.heapgrowthlimit]: [96m]
- [dalvik.vm.heapidealfree]: [8388608]
- [dalvik.vm.heapsize]: [384m]
- [dalvik.vm.heapstartsize]: [8m]
- [dalvik.vm.heaputilization]: [0.25]
- [dalvik.vm.stack-trace-file]: [/data/anr/traces.txt]
下面來看一下startVm()中的最後幾句:
- if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
- ALOGE("JNI_CreateJavaVM failed\n");
- goto bail;
- }
startVm()在最後會調用JNI_CreateJavaVM()來建立虛擬機。這裏順便看一下JNI_CreateJavaVM()的這段說明:」Java虛擬機對象JavaVm對象每一個進程有一個,JNI環境變量JNIEnv每一個線程有一個「。這裏也告訴咱們,在寫JNI代碼時要注意:
JNIEnv不能在任意線程中使用,必須是本來就是Java線程(Java代碼經過JNI調用native代碼時,發起調用的那個確定是Java線程),或者是讓已有的native線程經過JNI來attach到Java環境。具體這裏不作詳細介紹,感興趣的讀者能夠參考Oracle官方文檔http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html。在JNI_CreateJavaVM()調用成功後虛擬機VM就已經建立好了,接下來就能夠進行JNI相關調用了。
註冊JNI函數
建立好了虛擬機,接下來要給虛擬機註冊一些JNI函數。不知道各位讀者有沒有想過,這裏爲何要註冊JNI函數呢?沒錯,由於在基於虛擬機的Java世界裏,Java並非萬能的,它用到的不少方法(例如:音頻、視頻相關、Binder等)都須要以native的方式實現,而這些方法就須要虛擬機以JNI的方式進行加載。
@/frameworks/base/core/jni/AndroidRuntime.cpp
- {
-
- <span style="white-space:pre"> </span>
- androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
-
-
- ALOGV("--- registering native functions ---\n");
-
-
-
- env->PushLocalFrame(200);
-
-
- if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
- env->PopLocalFrame(NULL);
- return -1;
- }
- env->PopLocalFrame(NULL);
-
-
-
-
-
- return 0;
- }
咱們來看一下register_jni_procs()的代碼:
- static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
- {
- for (size_t i = 0; i < count; i++) {
- if (array[i].mProc(env) < 0) {
- #ifndef NDEBUG
- ALOGD("----------!!! %s failed to load\n", array[i].mName);
- #endif
- return -1;
- }
- }
- return 0;
- }
看一下從startReg()傳過來的參數gRegJNI:
- static const RegJNIRec gRegJNI[] = {
- REG_JNI(register_android_debug_JNITest),
- REG_JNI(register_com_android_internal_os_RuntimeInit),
- REG_JNI(register_android_os_SystemClock),
- REG_JNI(register_android_util_EventLog),
- REG_JNI(register_android_util_Log),
- REG_JNI(register_android_util_FloatMath),
- REG_JNI(register_android_text_format_Time),
- REG_JNI(register_android_content_AssetManager),
- REG_JNI(register_android_content_StringBlock),
- REG_JNI(register_android_content_XmlBlock),
- REG_JNI(register_android_emoji_EmojiFactory),
- REG_JNI(register_android_text_AndroidCharacter),
- REG_JNI(register_android_text_AndroidBidi),
- REG_JNI(register_android_view_InputDevice),
- REG_JNI(register_android_view_KeyCharacterMap),
- REG_JNI(register_android_os_Process),
- REG_JNI(register_android_os_SystemProperties),
- REG_JNI(register_android_os_Binder),
- REG_JNI(register_android_os_Parcel),
- REG_JNI(register_android_view_DisplayEventReceiver),
- REG_JNI(register_android_nio_utils),
- REG_JNI(register_android_graphics_Graphics),
- REG_JNI(register_android_view_GraphicBuffer),
- REG_JNI(register_android_view_GLES20DisplayList),
- REG_JNI(register_android_view_GLES20Canvas),
- REG_JNI(register_android_view_HardwareRenderer),
- REG_JNI(register_android_view_Surface),
- REG_JNI(register_android_view_SurfaceControl),
- REG_JNI(register_android_view_SurfaceSession),
- REG_JNI(register_android_view_TextureView),
- REG_JNI(register_com_google_android_gles_jni_EGLImpl),
- REG_JNI(register_com_google_android_gles_jni_GLImpl),
- REG_JNI(register_android_opengl_jni_EGL14),
- REG_JNI(register_android_opengl_jni_EGLExt),
- REG_JNI(register_android_opengl_jni_GLES10),
- REG_JNI(register_android_opengl_jni_GLES10Ext),
- REG_JNI(register_android_opengl_jni_GLES11),
- REG_JNI(register_android_opengl_jni_GLES11Ext),
- REG_JNI(register_android_opengl_jni_GLES20),
- REG_JNI(register_android_opengl_jni_GLES30),
-
- REG_JNI(register_android_graphics_Bitmap),
- REG_JNI(register_android_graphics_BitmapFactory),
- REG_JNI(register_android_graphics_BitmapRegionDecoder),
- REG_JNI(register_android_graphics_Camera),
- REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
- REG_JNI(register_android_graphics_Canvas),
- REG_JNI(register_android_graphics_ColorFilter),
- REG_JNI(register_android_graphics_DrawFilter),
- REG_JNI(register_android_graphics_Interpolator),
- REG_JNI(register_android_graphics_LayerRasterizer),
- REG_JNI(register_android_graphics_MaskFilter),
- REG_JNI(register_android_graphics_Matrix),
- REG_JNI(register_android_graphics_Movie),
- REG_JNI(register_android_graphics_NinePatch),
- REG_JNI(register_android_graphics_Paint),
- REG_JNI(register_android_graphics_Path),
- REG_JNI(register_android_graphics_PathMeasure),
- REG_JNI(register_android_graphics_PathEffect),
- REG_JNI(register_android_graphics_Picture),
- REG_JNI(register_android_graphics_PorterDuff),
- REG_JNI(register_android_graphics_Rasterizer),
- REG_JNI(register_android_graphics_Region),
- REG_JNI(register_android_graphics_Shader),
- REG_JNI(register_android_graphics_SurfaceTexture),
- REG_JNI(register_android_graphics_Typeface),
- REG_JNI(register_android_graphics_Xfermode),
- REG_JNI(register_android_graphics_YuvImage),
- REG_JNI(register_android_graphics_pdf_PdfDocument),
-
- REG_JNI(register_android_database_CursorWindow),
- REG_JNI(register_android_database_SQLiteConnection),
- REG_JNI(register_android_database_SQLiteGlobal),
- REG_JNI(register_android_database_SQLiteDebug),
- REG_JNI(register_android_os_Debug),
- REG_JNI(register_android_os_FileObserver),
- REG_JNI(register_android_os_FileUtils),
- REG_JNI(register_android_os_MessageQueue),
- REG_JNI(register_android_os_SELinux),
- REG_JNI(register_android_os_Trace),
- REG_JNI(register_android_os_UEventObserver),
- REG_JNI(register_android_net_LocalSocketImpl),
- REG_JNI(register_android_net_NetworkUtils),
- REG_JNI(register_android_net_TrafficStats),
- REG_JNI(register_android_net_wifi_WifiNative),
- REG_JNI(register_android_os_MemoryFile),
- REG_JNI(register_com_android_internal_os_ZygoteInit),
- REG_JNI(register_android_hardware_Camera),
- REG_JNI(register_android_hardware_camera2_CameraMetadata),
- REG_JNI(register_android_hardware_SensorManager),
- REG_JNI(register_android_hardware_SerialPort),
- REG_JNI(register_android_hardware_UsbDevice),
- REG_JNI(register_android_hardware_UsbDeviceConnection),
- REG_JNI(register_android_hardware_UsbRequest),
- REG_JNI(register_android_media_AudioRecord),
- REG_JNI(register_android_media_AudioSystem),
- REG_JNI(register_android_media_AudioTrack),
- REG_JNI(register_android_media_JetPlayer),
- REG_JNI(register_android_media_RemoteDisplay),
- REG_JNI(register_android_media_ToneGenerator),
-
- REG_JNI(register_android_opengl_classes),
- REG_JNI(register_android_server_NetworkManagementSocketTagger),
- REG_JNI(register_android_server_Watchdog),
- REG_JNI(register_android_ddm_DdmHandleNativeHeap),
- REG_JNI(register_android_backup_BackupDataInput),
- REG_JNI(register_android_backup_BackupDataOutput),
- REG_JNI(register_android_backup_FileBackupHelperBase),
- REG_JNI(register_android_backup_BackupHelperDispatcher),
- REG_JNI(register_android_app_backup_FullBackup),
- REG_JNI(register_android_app_ActivityThread),
- REG_JNI(register_android_app_NativeActivity),
- REG_JNI(register_android_view_InputChannel),
- REG_JNI(register_android_view_InputEventReceiver),
- REG_JNI(register_android_view_InputEventSender),
- REG_JNI(register_android_view_InputQueue),
- REG_JNI(register_android_view_KeyEvent),
- REG_JNI(register_android_view_MotionEvent),
- REG_JNI(register_android_view_PointerIcon),
- REG_JNI(register_android_view_VelocityTracker),
-
- REG_JNI(register_android_content_res_ObbScanner),
- REG_JNI(register_android_content_res_Configuration),
-
- REG_JNI(register_android_animation_PropertyValuesHolder),
- REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
- REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
- };
REG_JNI是系統定義的一個宏:
- #ifdef NDEBUG
- #define REG_JNI(name) { name }
- struct RegJNIRec {
- int (*mProc)(JNIEnv*);
- };
- #else
- #define REG_JNI(name) { name, #name }
- struct RegJNIRec {
- int (*mProc)(JNIEnv*);
- const char* mName;
- };
- #endif
以gRegJNI數組中的一項爲例,REG_JNI(register_android_debug_JNITest) 展開REG_JNI後變爲:
- { register_android_debug_JNITest, "register_android_debug_JNITest" }
因此當register_jni_procs()中調用mProcess時,最終調用的是android_debug_JNITest類中的register_android_debug_JNITest:
- int register_android_debug_JNITest(JNIEnv* env)
- {
- return jniRegisterNativeMethods(env, "android/debug/JNITest",
- gMethods, NELEM(gMethods));
- }
到這裏JNI註冊就講完了。
ZygoteInit初始化
在JNI註冊完成後,讓咱們再回頭繼續看AndroidRuntime中start函數:
- env->CallStaticVoidMethod(startClass, startMeth, strArray);
在start()中經過JNI調用ZygoteInit類的main()方法,這個main()方法即便從native世界到Java世界的入口。
@/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
- public static void main(String argv[]) {
- try {
-
- SamplingProfilerIntegration.start();
-
- registerZygoteSocket();
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
- SystemClock.uptimeMillis());
- preload();
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
- SystemClock.uptimeMillis());
-
-
- SamplingProfilerIntegration.writeZygoteSnapshot();
-
-
- gc();
-
-
-
- Trace.setTracingEnabled(false);
-
-
- if (argv.length != 2) {
- throw new RuntimeException(argv[0] + USAGE_STRING);
- }
-
- if (argv[1].equals("start-system-server")) {
- startSystemServer();
- } else if (!argv[1].equals("")) {
- throw new RuntimeException(argv[0] + USAGE_STRING);
- }
-
- Log.i(TAG, "Accepting command socket connections");
-
- runSelectLoop();
-
- closeServerSocket();
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- Log.e(TAG, "Zygote died with exception", ex);
- closeServerSocket();
- throw ex;
- }
- }
簡單總結一下ZygoteInit類中main()函數主要作了以下幾件事:
- 註冊Zygote用的socket
- 類和資源的預加載
- 啓動system_server進程
- 進入一個死循環,等待接收和處理socket事件
接下來將對它們一一進行分析。
registerZygoteSocket()方法
registerZygoteSocket()方法的實現以下:
- private static void registerZygoteSocket() {
- if (sServerSocket == null) {
- int fileDesc;
- try {
- String env = System.getenv(ANDROID_SOCKET_ENV);
- fileDesc = Integer.parseInt(env);
- } catch (RuntimeException ex) {
- throw new RuntimeException(
- ANDROID_SOCKET_ENV + " unset or invalid", ex);
- }
-
- try {
- sServerSocket = new LocalServerSocket(
- createFileDescriptor(fileDesc));
- } catch (IOException ex) {
- throw new RuntimeException(
- "Error binding to local socket '" + fileDesc + "'", ex);
- }
- }
- }
registerZygoteSocket()方法比較簡單,就是建立了一個服務端Socket。
在Zygote中經過preload()方法完成類和資源的加載,它的實現以下:api
- static void preload() {
- preloadClasses();
- preloadResources();
- preloadOpenGL();
- }
先看一下preloadClasses():數組
- private static void preloadClasses() {
- final VMRuntime runtime = VMRuntime.getRuntime();
-
- InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(
- PRELOADED_CLASSES);
- if (is == null) {
- Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
- } else {
- Log.i(TAG, "Preloading classes...");
- long startTime = SystemClock.uptimeMillis();
-
-
- setEffectiveGroup(UNPRIVILEGED_GID);
- setEffectiveUser(UNPRIVILEGED_UID);
-
-
-
- float defaultUtilization = runtime.getTargetHeapUtilization();
- runtime.setTargetHeapUtilization(0.8f);
-
-
- System.gc();
- runtime.runFinalizationSync();
- Debug.startAllocCounting();
-
- try {
- BufferedReader br
- = new BufferedReader(new InputStreamReader(is), 256);
-
- int count = 0;
- String line;
- while ((line = br.readLine()) != null) {
-
- line = line.trim();
- if (line.startsWith("#") || line.equals("")) {
- continue;
- }
-
- try {
- if (false) {
- Log.v(TAG, "Preloading " + line + "...");
- }
- Class.forName(line);
- if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
- if (false) {
- Log.v(TAG,
- " GC at " + Debug.getGlobalAllocSize());
- }
- System.gc();
- runtime.runFinalizationSync();
- Debug.resetGlobalAllocSize();
- }
- count++;
- } catch (ClassNotFoundException e) {
- Log.w(TAG, "Class not found for preloading: " + line);
- } catch (Throwable t) {
- Log.e(TAG, "Error preloading " + line + ".", t);
- if (t instanceof Error) {
- throw (Error) t;
- }
- if (t instanceof RuntimeException) {
- throw (RuntimeException) t;
- }
- throw new RuntimeException(t);
- }
- }
-
- Log.i(TAG, "...preloaded " + count + " classes in "
- + (SystemClock.uptimeMillis()-startTime) + "ms.");
- } catch (IOException e) {
- Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
- } finally {
- IoUtils.closeQuietly(is);
-
- runtime.setTargetHeapUtilization(defaultUtilization);
-
-
- runtime.preloadDexCaches();
-
- Debug.stopAllocCounting();
-
-
- setEffectiveUser(ROOT_UID);
- setEffectiveGroup(ROOT_GID);
- }
- }
- }
preloadClasses()的實現很簡單,這裏說一下preloaded-classes文件:服務器
- # Classes which are preloaded by com.android.internal.os.ZygoteInit.
- # Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java.
- # MIN_LOAD_TIME_MICROS=1250
- # MIN_PROCESSES=10
- android.R$styleable
- android.accounts.Account
- android.accounts.Account$1
- android.accounts.AccountManager
- android.accounts.AccountManager$12
- android.accounts.AccountManager$13
- android.accounts.AccountManager$6
- android.accounts.AccountManager$AmsTask
- android.accounts.AccountManager$AmsTask$1
- android.accounts.AccountManager$AmsTask$Response
在Android4.4的源代碼中有2782行,也就說這裏在系統啓動時須要預加載兩千多個類,而這僅僅是源代碼,在手機廠商的代碼中,須要進行預加載的類的數量將會超過這個數。preloaded-classes文件時由WritePreloadedClassFile類生成的。WritePreloadedClassFile將某個類加入預加載文件preloaded-classes中的條件時:該類被很多於10個進程使用,而且家中該類好使超過1250微秒。WritePreloadedClassFile裏面的實現很是簡單,感興趣的讀者能夠自行閱讀。oracle
- static final int MIN_LOAD_TIME_MICROS = 1250;
-
- static final int MIN_PROCESSES = 10;
這裏我簡單估算了一下,在Android4.4中預加載這些類須要4秒鐘做用,這對於系統啓動來講是一個比較長的時間,所以在進行系統啓動速度的優化時,這裏能夠做爲一個優化大點。
在看preloadClass的代碼時有些讀者看的setEffectiveUser的幾句代碼不明白什麼意思:
- private static void preloadClasses() {
- ......
-
- setEffectiveGroup(UNPRIVILEGED_GID);
- setEffectiveUser(UNPRIVILEGED_UID);
- ......
- } finally {
- ......
-
- setEffectiveUser(ROOT_UID);
- setEffectiveGroup(ROOT_GID);
- }
- }
- }
以setEffectiveUser爲例看一下它的實現:
- private static void setEffectiveUser(int uid) {
- int errno = setreuid(ROOT_UID, uid);
- if (errno != 0) {
- Log.e(TAG, "setreuid() failed. errno: " + errno);
- }
- }
- static native int setreuid(int ruid, int euid);
能夠看出這裏setEffectiveUser這幾句的意思是:在類加載以前臨時下降euid(真實用戶ID)權限,加載完成後恢復。關於Linux各類userid的說明以下:
有效用戶ID
有效用戶ID(Effective UID,即EUID)與有效用戶組ID(Effective Group ID,即EGID)在建立與訪問文件的時候發揮做用;具體來講,建立文件時,系統內核將根據建立文件的進程的EUID與EGID設定文件的全部者/組屬性,而在訪問文件時,內核亦根據訪問進程的EUID與EGID決定其可否訪問文件。
真實用戶ID
真實用戶ID(Real UID,即RUID)與真實用戶組ID(Real GID,即RGID)用於辨識進程的真正全部者,且會影響到進程發送信號的權限。沒有超級用戶權限的進程僅在其RUID與目標進程的RUID相匹配時才能向目標進程發送信號,例如在父子進程間,子進程從父進程處繼承了認證信息,使得父子進程間能夠互相發送信號。
暫存用戶ID
暫存用戶ID(Saved UID,即SUID)於以提高權限運行的進程暫時須要作一些不需特權的操做時使用,這種狀況下進程會暫時將本身的有效用戶ID從特權用戶(常爲root)對應的UID變爲某個非特權用戶對應的UID,然後將原有的特權用戶UID複製爲SUID暫存;以後當進程完成不需特權的操做後,進程使用SUID的值重置EUID以從新得到特權。在這裏須要說明的是,無特權進程的EUID值只能設爲與RUID、SUID與EUID(也即不改變)之一相同的值。
文件系統用戶ID
文件系統用戶ID(File System UID,即FSUID)在Linux中使用,且只用於對文件系統的訪問權限控制,在沒有明確設定的狀況下與EUID相同(若FSUID爲root的UID,則SUID、RUID與EUID必至少有一亦爲root的UID),且EUID改變也會影響到FSUID。設立FSUID是爲了容許程序(如NFS服務器)在不需獲取向給定UID帳戶發送信號的狀況下以給定UID的權限來限定本身的文件系統權限。
這段代碼轉自http://zh.wikipedia.org/wiki/%E7%94%A8%E6%88%B7ID
那這裏這樣作的用意何在?我猜這裏是爲了保證預加載的類是全部的用戶都是可用的。
預加載資源的代碼以下:
- private static void preloadResources() {
- final VMRuntime runtime = VMRuntime.getRuntime();
-
- Debug.startAllocCounting();
- try {
- System.gc();
- runtime.runFinalizationSync();
- mResources = Resources.getSystem();
- mResources.startPreloading();
- if (PRELOAD_RESOURCES) {
- Log.i(TAG, "Preloading resources...");
-
- long startTime = SystemClock.uptimeMillis();
- TypedArray ar = mResources.obtainTypedArray(
- com.android.internal.R.array.preloaded_drawables);
- int N = preloadDrawables(runtime, ar);
- ar.recycle();
- Log.i(TAG, "...preloaded " + N + " resources in "
- + (SystemClock.uptimeMillis()-startTime) + "ms.");
-
- startTime = SystemClock.uptimeMillis();
- ar = mResources.obtainTypedArray(
- com.android.internal.R.array.preloaded_color_state_lists);
- N = preloadColorStateLists(runtime, ar);
- ar.recycle();
- Log.i(TAG, "...preloaded " + N + " resources in "
- + (SystemClock.uptimeMillis()-startTime) + "ms.");
- }
- mResources.finishPreloading();
- } catch (RuntimeException e) {
- Log.w(TAG, "Failure preloading resources", e);
- } finally {
- Debug.stopAllocCounting();
- }
- }
preloadResources的加載過程又分爲加載Drawable和加載Color。
除了加載類和資源,還會加載OpenGL的一些東西:
- private static void preloadOpenGL() {
- if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
- EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- }
- }
在建立socket和資源加載先後有這麼兩句:
- SamplingProfilerIntegration.start();
-
- registerZygoteSocket();
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
- SystemClock.uptimeMillis());
- preload();
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
- SystemClock.uptimeMillis());
-
- SamplingProfilerIntegration.writeZygoteSnapshot();
因此,這裏SamplingProfilerIntegration統計的是建立socket和類及資源初始化的時間。
啓動system_server
- private static boolean startSystemServer()
- throws MethodAndArgsCaller, RuntimeException {
- long capabilities = posixCapabilitiesAsBits(
- OsConstants.CAP_KILL,
- OsConstants.CAP_NET_ADMIN,
- OsConstants.CAP_NET_BIND_SERVICE,
- OsConstants.CAP_NET_BROADCAST,
- OsConstants.CAP_NET_RAW,
- OsConstants.CAP_SYS_MODULE,
- OsConstants.CAP_SYS_NICE,
- OsConstants.CAP_SYS_RESOURCE,
- OsConstants.CAP_SYS_TIME,
- OsConstants.CAP_SYS_TTY_CONFIG
- );
-
- String args[] = {
- "--setuid=1000",
- "--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
- "--capabilities=" + capabilities + "," + capabilities,
- "--runtime-init",
- "--nice-name=system_server",
- "com.android.server.SystemServer",
- };
- ZygoteConnection.Arguments parsedArgs = null;
-
- int pid;
-
- try {
- parsedArgs = new ZygoteConnection.Arguments(args);
- ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
- ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
-
-
- pid = Zygote.forkSystemServer(
- parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids,
- parsedArgs.debugFlags,
- null,
- parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- } catch (IllegalArgumentException ex) {
- throw new RuntimeException(ex);
- }
-
-
- if (pid == 0) {
- handleSystemServerProcess(parsedArgs);
- }
-
- return true;
- }
這裏前面的一大段代碼主要是在爲fork準備參數parsedArgs,而後Zygote會forkSystemServer來建立system_server,forkSystemServer()方法最終會調用Linux中的fork()。
runSelectLoop()方法
在建立system_server後,Zygote調用runSelectLoop()進入到一個死循環中:
- private static void runSelectLoop() throws MethodAndArgsCaller {
- ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
- ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
- FileDescriptor[] fdArray = new FileDescriptor[4];
-
- fds.add(sServerSocket.getFileDescriptor());
- peers.add(null);
-
- int loopCount = GC_LOOP_COUNT;
- while (true) {
- int index;
-
-
- if (loopCount <= 0) {
- gc();
- loopCount = GC_LOOP_COUNT;
- } else {
- loopCount--;
- }
-
-
- try {
- fdArray = fds.toArray(fdArray);
- index = selectReadable(fdArray);
- } catch (IOException ex) {
- throw new RuntimeException("Error in select()", ex);
- }
-
- if (index < 0) {
- throw new RuntimeException("Error in select()");
- } else if (index == 0) {
- ZygoteConnection newPeer = acceptCommandPeer();
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {
- boolean done;
- done = peers.get(index).runOnce();
-
- if (done) {
- peers.remove(index);
- fds.remove(index);
- }
- }
- }
- }
下面是selcetReadable方法的代碼:
- static native int selectReadable(FileDescriptor[] fds) throws IOException;
selectReadable的native實如今com_android_internal_os_ZygoteInit.cpp中。
Zygote接收到socket客戶端的連接後會將其(客戶端Socket)保存到一個ZygoteConnection對象中,而後保存到peers
- private static ZygoteConnection acceptCommandPeer() {
- try {
- return new ZygoteConnection(sServerSocket.accept());
- } catch (IOException ex) {
- throw new RuntimeException(
- "IOException during accept()", ex);
- }
- }
最後,客戶端的請求會有ZygoteConnection的runOnce來處理。