《深入理解Android(卷1)》笔记 4.第四章 深入理解zygote
2012-12-17 10:19 ...平..淡... 阅读(1936) 评论(0) 编辑 收藏 举报第4章 深入理解zygote
知识点1:zygote分析
关于zygote这一部分,我对它的流程归纳如下:
(1) app_main.cpp类的main方法,调用AppRuntime类的start方法。 (2) 该start方法执行3个过程: (2.1)创建虚拟机:调用startVm方法。 (2.2)注册JNI方法:调用startReg方法。 (2.3)通过JNI调用java方法:env->callStaticVoidMethod方法。 分析 (2.1) 该方法确定了一些参数,用于创建虚拟机(调用JNI_createJavaVM方法创建虚拟机) (2.2) 为了让java世界使用native方法,所以提前注册这些方法。用到了regitster_jni_procs方法,用到了gRegJNI[]数组....(需要分析该数组) (2.3) 参数是zygoteInit,true 实际调用的是zygoteInit.java的main方法,由此进入了java的世界。 (2.3.1)注册zygote用的socket:registerZygoteSocket()---->建立IPC通信服务端----->其实就是创建了一个服务端socket (2.3.2)预加载类和资源: preloadClasses():如果某些类的加载速度>1250ms,就会被写到preload_classes文件中,进行预加载。 preloadResources():加载framework-res.apk的资源。 (2.3.3)启动system_server进程:调用startSystemServer方法。 (2.3.4)有求必应之等待请求: 调用runSelectLoopMode()方法等待请求 (2.3.5)caller.run(); 分析 (2.3.3)调用forkSystemServer()方法创建了system_server进程,然后调用handleSystemServerProcess方法。 (2.3.4)处理客户连接和客户请求。其中客户在zygote中用zygoteConnection对象来表示;客户的请求由zygoteConnection的runOnce方法来处理。
现在开始详细分析:
zygote最初名字是“app_process”,这个名字在Android.mk文件中指定的,但在运行过程中,app_process通过Linux下的pctrl系统调用换名为“zygote”。
zygote的原型app_process所对应的源文件是app_main.cpp。
1.main方法分析
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int main(int argc, const char* const argv[]) { /* Zygote进程由init通过fork而来,回顾init.rc中设置的启动参数: -Xzygote /system/bin --zygote --start-system-server */ // 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 //调用Appruntime的addVmArguments int i = runtime.addVmArguments(argc, argv); // Next arg is parent directory,设置runtime的mParentDir为 /system/bin if (i < argc) { runtime.mParentDir = argv[i++]; } // Next arg is startup classname or "--zygote" if (i < argc) { arg = argv[i++]; if (0 == strcmp("--zygote", arg)) { //我们传入的参数满足if的条件,而且下面的startSystemServer的值为true bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false; struct stat buf; char *filename = "/data/blcr/zygote.blcr"; char blcr[8];0 property_get("sys.service.blcr.running", blcr, "0"); if (strcmp(blcr, "1") == 0 && stat(filename, &buf) == 0) { unlink(filename); } property_get("persist.service.blcr.enable", blcr, "0"); if(stat(filename, &buf) == 0 && strcmp(blcr, "1") == 0){ //checkpoint exists setArgv0(argv0, "cr_restore"); set_process_name("cr_restore"); blcr_restart(filename); }else{ setArgv0(argv0, "zygote"); //设置本进程的名称为zygote,就是在这里完成”换名” set_process_name("zygote"); //(1)调用runtime的start,注意第二个参数startSystemServer为true。 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; } }
zygote的重要功能都是由AppRuntime的start方法来完成的。因此下面分析AppRuntime。
2.AppRuntime分析
AppRuntime类的声明和实现都在app_main.cpp中,它继承自AndroidRuntime类。
关系图:
AppRuntime重载了onStarted、onZygoteInit和onExit方法。
在分析main方法时,该方法中调用了AppRuntime类对象的start方法,其实是调用了基类AndroidRuntime的start方法。分析该方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". * * Passes the main function two arguments, the class name and the specified * options string. */ void AndroidRuntime::start(const char* className, const char* options) { //className的值是”com.android.internal.os.ZygoteInit”。 //startSystemServer的值是true。 ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n", className != NULL ? className : "(unknown)"); blockSigpipe(); //处理SIGPIPE信号。 /* * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */ if (strcmp(options, "start-system-server") == 0) { /* 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"); if (rootDir == NULL) { //如果环境变量中没有ANDROID_ROOT,则新增该变量,并设置值为”/system”。 rootDir = "/system"; if (!hasDir("/system")) { LOG_FATAL("No root directory specified, and /android does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); } //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); /* start the virtual machine */ JNIEnv* env; //(1)创建虚拟机 if (startVm(&mJavaVM, &env) != 0) { return; } onVmCreated(env); /* * Register android functions. */ //(2)注册JNI函数 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } /* * We want to call main() with a String array with arguments in it. * At present we have two arguments, the class name and an option string. * Create an array to hold them. */ jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); //创建一个有两个元素的String数组,即Java代码:String strArray[] = new String[2] strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); //设置第一个元素为”com.android.internal.os.ZygoteInit”. env->SetObjectArrayElement(strArray, 0, classNameStr); optionsStr = env->NewStringUTF(options); //设置第二个元素为”true”,注意着两个元素都是String类型,即字符串。 env->SetObjectArrayElement(strArray, 1, optionsStr); /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { //找到ZygoteInit类的static main函数的jMethodId. 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 { //(3)通过JNI调用java函数,注意调用的是main方法。在调用ZygoteInit的main方法后,zygote便进入了Java世界!也就是说,zygote是开创Android系统中Java世界的盘古(作者的解释~~) env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName); ALOGD("Shutting down VM\n"); //zygote退出,正常情况下,zygote不需要退出。 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"); }
分析AndroidRuntime.cpp中3个关键点( (1)(2)(3) )
(1) 创建虚拟机-------startVm
这个函数中确定了一些参数(创建虚拟机所用);然后调用了虚拟机创建函数。参数不分析了,作者列出了一个参考的网页:Dalvik/Docs/Dexopt.html (译文)。看最后有个JNI_CreateJavaVM方法创建虚拟机,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * Start the Dalvik Virtual Machine. * * Various arguments, most determined by system properties, are passed in. * The "mOptions" vector is updated. * * Returns 0 on success. */ 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 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 is neither true nor false; fall back on kernel parameter */ 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, ""); /* route exit() to our handler */ opt.extraInfo = (void*) runtime_exit; opt.optionString = "exit"; mOptions.add(opt); /* route fprintf() to our handler */ opt.extraInfo = (void*) runtime_vfprintf; opt.optionString = "vfprintf"; mOptions.add(opt); /* register the framework-specific "is sensitive thread" hook */ opt.extraInfo = (void*) runtime_isSensitiveThread; opt.optionString = "sensitiveThread"; mOptions.add(opt); opt.extraInfo = NULL; /* enable verbose; standard options are { jni, gc, class } */ //options[curOpt++].optionString = "-verbose:jni"; opt.optionString = "-verbose:gc"; mOptions.add(opt); //options[curOpt++].optionString = "-verbose:class"; /* * The default starting and maximum size of the heap. Larger * values should be specified in a product property override. */ 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); // Increase the main thread's interpreter stack size for bug 6315322. opt.optionString = "-XX:mainThreadStackSize=24K"; 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); } /* * Enable or disable dexopt features, such as bytecode verification and * calculation of register maps for precise GC. */ property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, ""); if (dexoptFlagsBuf[0] != '\0') { const char* opc; const char* val; opc = strstr(dexoptFlagsBuf, "v="); /* verification */ 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="); /* optimization */ 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"); /* register map */ if (opc != NULL) { opt.optionString = "-Xgenregmap"; mOptions.add(opt); /* turn on precise GC while we're at it */ opt.optionString = "-Xgc:precise"; mOptions.add(opt); } } /* enable debugging; set suspend=y to pause during VM init */ /* use android ADB transport */ 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) { /* extended JNI checking */ opt.optionString = "-Xcheck:jni"; mOptions.add(opt); /* set a cap on JNI global references */ opt.optionString = "-Xjnigreflimit:2000"; mOptions.add(opt); /* with -Xcheck:jni, this provides a JNI function call trace */ //opt.optionString = "-verbose:jni"; //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); } /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */ 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); } /* Force interpreter-only mode for selected methods */ 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) { /* perform additional DEX checksum tests */ opt.optionString = "-Xcheckdexsum"; mOptions.add(opt); } if (logStdio) { /* convert stdout/stderr to log messages */ opt.optionString = "-Xlog-stdio"; mOptions.add(opt); } if (enableAssertBuf[4] != '\0') { /* accept "all" to mean "all classes and packages" */ 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); } /* extra options; parse this late so it overrides others */ property_get("dalvik.vm.extra-opts", extraOptsBuf, ""); parseExtraOpts(extraOptsBuf); /* Set the properties for locale */ { 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); } /* * We don't have /tmp on the device, but we often have an SD card. Apps * shouldn't use this, but some test suites might want to exercise it. */ 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; /* * Initialize the VM. * * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread. * If this call succeeds, the VM is ready, and we can start issuing * JNI calls. */ //调用JNI_CreateJavaVM创建虚拟机,pEnv返回当前线程的JNIEnv变量。 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); goto bail; } result = 0; bail: free(stackTraceFile); return result; }
(2) 注册JNI函数----startReg
此步骤的原因:因为后续Java世界一些函数需要用到native方式实现,所以需要提前注册这些函数。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * Register android native functions with the VM. */ /*static*/ int AndroidRuntime::startReg(JNIEnv* env) { /* * This hook causes all future threads created in this process to be * attached to the JavaVM. (This needs to go away in favor of JNI * Attach calls.) */ //设置Thread类的线程创建函数为javaCreateThreadEtc. androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); LOGV("--- registering native functions ---\n"); /* * Every "register" function calls one or more things that return * a local reference (e.g. FindClass). Because we haven't really * started the VM yet, they're all getting stored in the base frame * and never released. Use Push/Pop to manage the storage. */ env->PushLocalFrame(200); //注册JNI函数,gRegJNI是一个全局数组. if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); //createJavaThread("fubar", quickTest, (void*) "hello"); return 0; }
(2.1)分析register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0).代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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) { //调用数组元素的mProc函数 #ifndef NDEBUG LOGD("----------!!! %s failed to load\n", array[i].mName); #endif return -1; } } return 0; }
可以看出,这个函数主要调用的就是数组中的mProc函数。因此接下来需要分析数组和mProc函数。
(2.2)先分析数组(RegJNIRec类型,数组名为gRegJNI)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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_pim_EventRecurrence), 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_security_Md5MessageDigest), REG_JNI(register_android_text_AndroidCharacter), REG_JNI(register_android_text_AndroidBidi), REG_JNI(register_android_text_KeyCharacterMap), REG_JNI(register_android_os_Process), REG_JNI(register_android_os_Binder), REG_JNI(register_android_view_Display), REG_JNI(register_android_nio_utils), REG_JNI(register_android_graphics_PixelFormat), REG_JNI(register_android_graphics_Graphics), REG_JNI(register_android_view_Surface), REG_JNI(register_android_view_ViewRoot), REG_JNI(register_com_google_android_gles_jni_EGLImpl), REG_JNI(register_com_google_android_gles_jni_GLImpl), 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_graphics_Bitmap), //BEGIN: added by shenyutao REG_JNI(register_android_gif_decoder), //END : added by shenyutao REG_JNI(register_android_graphics_BitmapFactory), REG_JNI(register_android_graphics_BitmapRegionDecoder), REG_JNI(register_android_graphics_Camera), 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_Typeface), REG_JNI(register_android_graphics_Xfermode), REG_JNI(register_android_graphics_YuvImage), REG_JNI(register_com_android_internal_graphics_NativeUtils), REG_JNI(register_android_database_CursorWindow), REG_JNI(register_android_database_SQLiteCompiledSql), REG_JNI(register_android_database_SQLiteDatabase), REG_JNI(register_android_database_SQLiteDebug), REG_JNI(register_android_database_SQLiteProgram), REG_JNI(register_android_database_SQLiteQuery), REG_JNI(register_android_database_SQLiteStatement), 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_ParcelFileDescriptor), REG_JNI(register_android_os_Power), REG_JNI(register_android_os_StatFs), REG_JNI(register_android_os_SystemProperties), 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_WifiManager), REG_JNI(register_android_nfc_NdefMessage), REG_JNI(register_android_nfc_NdefRecord), 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_SensorManager), 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_ToneGenerator), REG_JNI(register_android_opengl_classes), REG_JNI(register_android_bluetooth_HeadsetBase), REG_JNI(register_android_bluetooth_BluetoothAudioGateway), REG_JNI(register_android_bluetooth_BluetoothSocket), REG_JNI(register_android_bluetooth_ScoSocket), REG_JNI(register_android_server_BluetoothService), REG_JNI(register_android_server_BluetoothEventLoop), REG_JNI(register_android_server_BluetoothA2dpService), REG_JNI(register_android_server_Watchdog), REG_JNI(register_android_message_digest_sha1), 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_NativeActivity), REG_JNI(register_android_view_InputChannel), REG_JNI(register_android_view_InputQueue), REG_JNI(register_android_view_KeyEvent), REG_JNI(register_android_view_MotionEvent), REG_JNI(register_android_content_res_ObbScanner), REG_JNI(register_android_content_res_Configuration), REG_JNI(register_android_blcr_checkpoint), };
REG_JNI是一个宏,看下其定义:
#ifdef NDEBUG #define REG_JNI(name) { name } struct RegJNIRec { int (*mProc)(JNIEnv*); }; …… #endif
可以看出,mProc包含在宏定义中,取数组中第一个元素REG_JNI(register_android_debug_JNITest)来分析下:[--->android_debug_JNITest.cpp]
int register_android_debug_JNITest(JNIEnv* env) { //为android.debug.JNITest类注册它所需要的JNI函数。 return jniRegisterNativeMethods(env, "android/debug/JNITest", gMethods, NELEM(gMethods)); }
发现了吧,mProc就是为java类注册了JNI函数!
由此,虚拟机创建完毕,JNI函数也注册完成,下一步就是分析CallSaticVoidMethod函数了。通过这个函数,我们就将进入Java世界了~ ~O(∩_∩)O~
(3) 开创Java世界
通过AndroidRuntime::start的分析,可以知道Java世界的入口函数就是com.android.internal.os.ZygoteInit的main函数。(ps:该函数在2.2和2.3中存在差异,我还是按照2.3来分析(作者基于2.2))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static void main(String argv[]) { CheckPoint cp = new CheckPoint(); try { VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024); // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); //(1)预加载类和资源 preloadClasses(); //cacheRegisterMaps(); preloadResources(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); int blcr = SystemProperties.getInt("persist.service.blcr.enable", 0); if(blcr > 0) { preparsePackages(Environment.getRootDirectory(), "framework"); preparsePackages(Environment.getRootDirectory(), "app"); } // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gc(); if(blcr > 0){ cp.checkPoint("/data/blcr/zygote.blcr"); } //(2)注册zygote要使用的socket registerZygoteSocket(); // If requested, start system server directly from Zygote if (argv.length != 2) { throw new RuntimeException(argv[0] + USAGE_STRING); } if (argv[1].equals("true")) { startSystemServer(); //(3)启动system_server进程 } else if (!argv[1].equals("false")) { throw new RuntimeException(argv[0] + USAGE_STRING); } Log.i(TAG, "Accepting command socket connections"); if (ZYGOTE_FORK_MODE) { runForkMode(); } else { runSelectLoopMode(); //(4) } closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); //(5)Author means it’s important…so mark here. } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }
五大关键点,逐一分析:
(3.1)预加载类和资源preloadClasses()/preloadResources() [---->ZygoteInit.java]
(3.1.1) preloadClasses()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/ * Performs Zygote process initialization. Loads and initializes * commonly used classes. * * Most classes only cause a few hundred bytes to be allocated, but * a few will allocate a dozen Kbytes (in one case, 500+K). */ private static void preloadClasses() { final VMRuntime runtime = VMRuntime.getRuntime(); //预加载的信息都保存在PRELOADED_CLASSES 变量中(变量名为preloaded-classes,该文件目录为framework/base/preloaded-classes) InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream( PRELOADED_CLASSES); if (is == null) { Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); } else { //做一些统计和准备工作 Log.i(TAG, "Preloading classes..."); long startTime = SystemClock.uptimeMillis(); // Drop root perms while running static initializers. setEffectiveGroup(UNPRIVILEGED_GID); setEffectiveUser(UNPRIVILEGED_UID); // Alter the target heap utilization. With explicit GCs this // is not likely to have any effect. float defaultUtilization = runtime.getTargetHeapUtilization(); runtime.setTargetHeapUtilization(0.8f); // Start with a clean slate. runtime.gcSoftReferences(); runtime.runFinalizationSync(); Debug.startAllocCounting(); try { BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); int count = 0; String line; //按行读取文件,忽略”#”开头的注释行 while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } try { if (Config.LOGV) { Log.v(TAG, "Preloading " + line + "..."); } //通过Java的反射来加载类,line中存储的是预加载的类名 Class.forName(line); if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { if (Config.LOGV) { Log.v(TAG, " GC at " + Debug.getGlobalAllocSize()); } runtime.gcSoftReferences(); 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 { // Restore default. runtime.setTargetHeapUtilization(defaultUtilization); Debug.stopAllocCounting(); // Bring back root. We'll need it later. setEffectiveUser(ROOT_UID); setEffectiveGroup(ROOT_GID); } } }
preloadClasses函数看起来如此简单,但是却要加载超级多的类(2.3中Preloaded-classes文件中有1834行之多)。
# 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.IAccountManager android.accounts.IAccountManager$Stub android.accounts.IAccountManager$Stub$Proxy android.app.Activity android.app.ActivityManagerNative android.app.ActivityManagerProxy ………………………..//一共1834行
这些类是怎么来的呢?framework/base/tools/preload工具会生成preloaded-classes文件。该工具会先判断每个类的加载时间是否>1250ms,超过这个时间的类就会被加载到preloaded-classes文件中,最后由preloadClasses预加载。由此可见,preloadClasses函数的执行时间比较长,这也是导致android系统启动慢的原因之一。
(3.1.2) preloadResources()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Load in commonly used resources, so they can be shared across * processes. * * These tend to be a few Kbytes, but are frequently in the 20-40K * range, and occasionally even larger. */ private static void preloadResources() { final VMRuntime runtime = VMRuntime.getRuntime(); Debug.startAllocCounting(); try { runtime.gcSoftReferences(); 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); 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); 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(); } }
该函数与preloadClasses类似,它主要用于加载framework-res.apk中的资源。
ps:在UI编程中经常使用的com.android.R.XXX资源是系统默认的资源,都是由zygote加载的。
(3.2)registerZygoteSocket函数------>建立IPC通信服务端
zygote及系统中其他程序的通信没有使用Binder,而是采用了基于AF_UNIX类型的socket。registerZygoteSocket的使命正是在于建立这个socket。见代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails */ private static void registerZygoteSocket() { if (sServerSocket == null) { int fileDesc; try { //从环境变量里取出Socket的fd。Zygote启动的时候是调用了fork和execve函数的,而这个环境变量是由execve传入。 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 { //创建服务端socket,这个socket将listen并accept客户端。 sServerSocket = new LocalServerSocket( createFileDescriptor(fileDesc)); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }
总结:registerZygoteSocket函数就是创建了一个服务端的socket。(这里提出两个问题:客户端是谁?服务端怎么处理客户端的消息?----->待解决)
(3.3)startSystemServer函数---->启动system_server
这个函数会创建Java世界系统Service所驻留的进程system_server,该进程是framework的核心。(author:如果它死了,就会导致zygote自杀…(⊙o⊙))
分析源码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { /* Hardcoded command line to start the system server */ String args[] = { //设置参数 "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", //设置进程名为system_server "com.android.server.SystemServer", //启动的类名 }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { //把上面的字符串数组转换为Arguments对象。 parsedArgs = new ZygoteConnection.Arguments(args); /* * Enable debugging of the system process if *either* the command line flags * indicate it should be debuggable or the ro.debuggable system property * is set to "1" */ int debugFlags = parsedArgs.debugFlags; if ("1".equals(SystemProperties.get("ro.debuggable"))) debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; /* Request to fork the system server process */ //创建system_server进程 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { //如果pid==0,则表示处于子进程中 //(1)system_server进程的工作 handleSystemServerProcess(parsedArgs); } return true; }
分水岭:zygote进行了一次”无性繁殖”,分裂出system_server进程。handleSystemServerProcess函数将在system_server中分析。
(3.4)runSelectLoopMode函数---->有求必应之等待请求
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time. * * @throws MethodAndArgsCaller in a child process when a main() should * be executed. */ private static void runSelectLoopMode() throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList(); ArrayList<ZygoteConnection> peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; /* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; } try { fdArray = fds.toArray(fdArray); /* selectReadable内部调用select,使用多路复用I/O模型。 当有客户端连接或有数据时,则selectReadable就会返回。*/ 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) { //有一个客户端连接上。注意:客户端在zygote的代表是ZygoteConnection。 ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done; //客户端发送了请求,peers.get返回但是ZygoteConnection。 //后续处理交给ZygoteConnection的runOnce函数来完成。 done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }
总结runSelectLoopMode的作用:
1.处理客户连接和客户请求。客户在zygote中由ZygoteConnection表示。
2.客户的请求由ZygoteConnection的runOnce来处理。
(至于zygote是如何处理请求的,在后续讨论)
(3.5) 也将在system_server中分析
关于Zygote的总结:
1.创建AppRuntime对象,并调用其start方法,此后活动由AppRuntime控制。
2.startVm创建java虚拟机,startReg注册JNI函数。
3.通过JNI调用com.android.internal.os.ZygoteInit类的main方法,进入java世界。
4.调用registerZygoteSocket,通过此函数,可以响应子孙后代的请求。通过preloadClasses、preloadResources为java世界添砖加瓦。
5.zygote觉得自己工作压力大,就调用startSystemServer方法创建了一个子进程system_server来为java世界服务。
6.zygote完成了java世界的初创工作,接下来就是调用runSelectLoopMode方法,自己去睡觉了。
Zygote的作用:
盘古:创建了java世界。
女娲:繁殖了framework的核心system_server进程。
知识点2:SystemServer分析(进程名即system_server)
(1) SystemServer的诞生
作为zygote的嫡长子,它是通过Zygote.forkSystemServer函数创建的(该函数是一个native函数,实现在dalvik_system_Zygote.c中)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* native public static int forkSystemServer(int uid, int gid, * int[] gids, int debugFlags, long permittedCapabilities, * long effectiveCapabilities); */ static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult) { pid_t pid; //根据参数,fork一个子进程 pid = forkAndSpecializeCommon(args, true); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) { int status; LOGI("System server process %d has been created", pid); gDvm.systemServerPid = pid; /* There is a slight window that the system server process has crashed * but it went unnoticed because we haven't published its pid yet. So * we recheck here just to make sure that all is well. */ //函数退出前须检查刚创建的子进程是否已经退出了 if (waitpid(pid, &status, WNOHANG) == pid) { //如果system_server退出了,Zygote就直接干掉自己。╮(╯▽╰)╭ LOGE("System server process %d has died. Restarting Zygote!", pid); kill(getpid(), SIGKILL); } } RETURN_INT(pid); }
再来分析上述的forkAndSpecializeCommon函数。代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * Utility routine to fork zygote and specialize the child process. */ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) { pid_t pid; uid_t uid = (uid_t) args[0]; gid_t gid = (gid_t) args[1]; ArrayObject* gids = (ArrayObject *)args[2]; u4 debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; int64_t permittedCapabilities, effectiveCapabilities; if (isSystemServer) { /* * Don't use GET_ARG_LONG here for now. gcc is generating code * that uses register d8 as a temporary, and that's coming out * scrambled in the child process. b/3138621 */ //permittedCapabilities = GET_ARG_LONG(args, 5); //effectiveCapabilities = GET_ARG_LONG(args, 7); permittedCapabilities = args[5] | (int64_t) args[6] << 32; effectiveCapabilities = args[7] | (int64_t) args[8] << 32; } else { permittedCapabilities = effectiveCapabilities = 0; } if (!gDvm.zygote) { dvmThrowException("Ljava/lang/IllegalStateException;", "VM instance not started with -Xzygote"); return -1; } if (!dvmGcPreZygoteFork()) { LOGE("pre-fork heap failed\n"); dvmAbort(); } //a.设置信号处理 setSignalHandler(); dvmDumpLoaderStats("zygote"); pid = fork(); //创建子进程 if (pid == 0) { //对子进程做一些处理 int err; /* The child process */ #ifdef HAVE_ANDROID_OS extern int gMallocLeakZygoteChild; gMallocLeakZygoteChild = 1; /* keep caps across UID change, unless we're staying root */ if (uid != 0) { err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); if (err < 0) { LOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno)); dvmAbort(); } } #endif /* HAVE_ANDROID_OS */ err = setgroupsIntarray(gids); if (err < 0) { LOGE("cannot setgroups(): %s", strerror(errno)); dvmAbort(); } err = setrlimitsFromArray(rlimits); if (err < 0) { LOGE("cannot setrlimit(): %s", strerror(errno)); dvmAbort(); } err = setgid(gid); if (err < 0) { LOGE("cannot setgid(%d): %s", gid, strerror(errno)); dvmAbort(); } err = setuid(uid); if (err < 0) { LOGE("cannot setuid(%d): %s", uid, strerror(errno)); dvmAbort(); } err = setCapabilities(permittedCapabilities, effectiveCapabilities); if (err != 0) { LOGE("cannot set capabilities (%llx,%llx): %s\n", permittedCapabilities, effectiveCapabilities, strerror(err)); dvmAbort(); } /* * Our system thread ID has changed. Get the new one. */ Thread* thread = dvmThreadSelf(); thread->systemTid = dvmGetSysThreadId(); /* configure additional debug options */ enableDebugFeatures(debugFlags); unsetSignalHandler(); gDvm.zygote = false; if (!dvmInitAfterZygote()) { LOGE("error in post-zygote initialization\n"); dvmAbort(); } } else if (pid > 0) { /* the parent process */ } return pid; }
a.分析setSignalHandler()函数。代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * configure sigchld handler for the zygote process * This is configured very late, because earlier in the dalvik lifecycle * we can fork() and exec() for the verifier/optimizer, and we * want to waitpid() for those rather than have them be harvested immediately. * * This ends up being called repeatedly before each fork(), but there's * no real harm in that. */ static void setSignalHandler() { int err; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigchldHandler; //b. err = sigaction (SIGCHLD, &sa, NULL); //设置信号处理函数,该信号是子进程死亡的信号 if (err < 0) { LOGW("Error setting SIGCHLD handler: %s", strerror(errno)); } }
b.分析sigchldHandler函数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * This signal handler is for zygote mode, since the zygote * must reap its children */ static void sigchldHandler(int s) { pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { /* Log process-death status that we care about. In general it is not safe to call LOG(...) from a signal handler because of possible reentrancy. However, we know a priori that the current implementation of LOG() is safe to call from a SIGCHLD handler in the zygote process. If the LOG() implementation changes its locking strategy or its use of syscalls within the lazy-init critical section, its use here may become unsafe. */ if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { LOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)\n", (int) pid, WEXITSTATUS(status)); } else { IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) { LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)\n", (int) pid, WEXITSTATUS(status)); } } } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != SIGKILL) { LOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d terminated by signal (%d)\n", (int) pid, WTERMSIG(status)); } else { IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) { LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, "Process %d terminated by signal (%d)\n", (int) pid, WTERMSIG(status)); } } #ifdef WCOREDUMP if (WCOREDUMP(status)) { LOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core\n", (int) pid); } #endif /* ifdef WCOREDUMP */ } /* * If the just-crashed process is the system_server, bring down zygote * so that it is restarted by init and system server will be restarted * from there. */ //如果死去的进程是SS,则zygote就干掉自己,做到了生死与共! if (pid == gDvm.systemServerPid) { LOG(LOG_INFO, ZYGOTE_LOG_TAG, "Exit zygote because system server (%d) has terminated\n", (int) pid); kill(getpid(), SIGKILL); } } if (pid < 0) { LOG(LOG_WARN, ZYGOTE_LOG_TAG, "Zygote SIGCHLD error in waitpid: %s\n",strerror(errno)); } }
为什么SystemServer这么重要?通过forkSystemServer下手分析一下。
4.3.2 SystemServer(简写SS)的重要使命
SS诞生后,就有了自己的使命,就和生父(额,生母?...)zygote分开了。分析其使命:
/* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); //SS的使命 }
继续分析handleSystemServerProcess函数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { //关闭从zygote继承下来的socket closeServerSocket(); /* * Pass the remaining arguments to SystemServer. * "--nice-name=system_server com.android.server.SystemServer" */ //调用zygoteInit函数 RuntimeInit.zygoteInit(parsedArgs.remainingArgs); /* should never reach here */ }
SS往下走,走到了RuntimeInit.java的静态函数---zygoteInit函数中,分析代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * The main function called when started through the zygote process. This * could be unified with main(), if the native code in finishInit() * were rationalized with Zygote startup.<p> * * Current recognized args: * <ul> * <li> --nice-name=<i>nice name to appear in ps</i> * <li> <code> [--] <start class name> <args> * </ul> * * @param argv arg strings */ public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller { // TODO: Doing this here works, but it seems kind of arbitrary. Find // a better place. The goal is to set it up for applications, but not // tools like am. System.setOut(new AndroidPrintStream(Log.INFO, "System.out")); System.setErr(new AndroidPrintStream(Log.WARN, "System.err")); commonInit(); //做一些常规初始化 zygoteInitNative(); //(a) native层的初始化 int curArg = 0; for ( /* curArg */ ; curArg < argv.length; curArg++) { String arg = argv[curArg]; if (arg.equals("--")) { curArg++; break; } else if (!arg.startsWith("--")) { break; } else if (arg.startsWith("--nice-name=")) { String niceName = arg.substring(arg.indexOf('=') + 1); Process.setArgV0(niceName); //设置进程名为niceName,即”system_server” } } if (curArg == argv.length) { Slog.e(TAG, "Missing classname argument to RuntimeInit!"); // let the process exit return; } // Remaining arguments are passed to the start class's static main String startClass = argv[curArg++]; String[] startArgs = new String[argv.length - curArg]; System.arraycopy(argv, curArg, startArgs, 0, startArgs.length); //(b) 调用startClass,也就是com.android.server.SystemServer类的main函数 invokeStaticMain(startClass, startArgs); }
分析(a)/(b)
(a) zygoteInitNative分析(是个native函数,实现在AndroidRuntime.cpp中)
static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }
问:gCurRuntime是什么? 分析:
在app_process的main函数中,
int main(int argc, const char* const argv[]) { AppRuntime runtime; //就是这里,接下来看下构造函数 }
一步步分析:
----->AppRuntime的定义
class AppRuntime : public AndroidRuntime
----->gCurRuntime定义的位置
static AndroidRuntime* gCurRuntime = NULL; //是全局变量
----->AndroidRuntime类的构造函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
AndroidRuntime::AndroidRuntime() { SkGraphics::Init(); //Skia库初始化 #if (LCD_BPP == 32) || (LCD_BPP == 24) // this sets our preference for 32bit images during decode // in case the src is opaque and 24bit SkImageDecoder::SetDeviceConfig(SkBitmap::kARGB_8888_Config); #else // this sets our preference for 16bit images during decode // in case the src is opaque and 24bit SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config); #endif // This cache is shared between browser native images, and java "purgeable" // bitmaps. This globalpool is for images that do not either use the java // heap, or are not backed by ashmem. See BitmapFactory.cpp for the key // java call site. SkImageRef_GlobalPool::SetRAMBudget(512 * 1024); // There is also a global font cache, but its budget is specified in code // see SkFontHost_android.cpp // Pre-allocate enough space to hold a fair number of options. mOptions.setCapacity(20); assert(gCurRuntime == NULL); // one per process gCurRuntime = this; //gCurRuntime被设置为AndroidRuntime对象自己 }
因为SS是从zygote中fork出来的,所以它也拥有zygote进程中定义的这个gCurRuntime,也就是AppRuntime对象。
分析完毕,那么它的onZygoteInit会做些什么呢?分析如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
virtual void onZygoteInit() { //与Binder有关,暂时不管 sp<ProcessState> proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } }
总结zygoteInitNative作用:一句话,SS调用zygoteInitNative后,将与Binder通信系统建立联系,这样SS就可以使用Binder了。
(b) invokeStaticMain函数分析
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Invokes a static "main(argv[]) method on class "className". * Converts various failing exceptions into RuntimeExceptions, with * the assumption that they will then cause the VM instance to exit. * * @param className Fully-qualified class name * @param argv Argument vector for main() */ private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { // We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); //参数中className是”com.android.server.SystemServer” Class<?> cl; try { cl = Class.forName(className); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } Method m; try { //找到com.android.server.SystemServer类的main函数,肯定有地方要调用它 m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { throw new RuntimeException( "Missing static main on " + className, ex); } catch (SecurityException ex) { throw new RuntimeException( "Problem getting static main on " + className, ex); } int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); //(c) 该异常的处理 }
(c) 根据注释,可以看到该异常是在zygoteInit类的main函数中被捕获。
if (argv[1].equals("true")) { startSystemServer(); …… } catch (MethodAndArgsCaller caller) { caller.run(); //(d) }
分析(d) :MethodAndArgsCaller类的run函数。其中MethodAndArgsCaller类也定义在ZygoteInit.java中。代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void run() { try { //这个mMethod为com.android.server.SystemServer的main函数。 mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } }
抛出的这个异常最后会导致com.android.server.SystemServer类的main函数被调用。
问:为什么不在invokeStaticMain中直接调用该main函数,而是通过抛出异常的方式呢?
答:作者解释(我还是觉得不懂):这个调用是在ZygoteInit.main函数中,相当于Native函数,即入口函数,位于堆栈的顶层。如果不采用抛异常的方式,而是在invokeStaticMain那里调用,则会浪费函数调用所占用的一些堆栈。这种抛异常的方式对是exec的一种近似模拟。
1. SystemServer的真面目
ZygoteInit分裂产生的SS,其实就是为了调用com.android.server.SystemServer的main函数---->改头换面了。分析该main函数:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static void main(String[] args) { if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { // If a device's clock is before 1970 (before 0), a lot of // APIs crash dealing with negative numbers, notably // java.io.File#setLastModified, so instead we fake it and // hope that time from cell towers or NTP fixes it // shortly. Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server"); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); //(e)加载libandroid_servers.so System.loadLibrary("android_servers"); //(f)调用native的init1函数 init1(args); }
(e) 加载libandroid_servers.so库,这个库包含的源码文件在framework/base/services/jni下。
(f)init1是native函数,在com_android_server_SystemServer.cpp中实现。代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
extern "C" int system_init(); static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) { system_init(); //(f1)调用该函数。 }
(f1)system_init的实现在system_init.cpp中,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
extern "C" status_t system_init() { LOGI("Entered system_init()"); //这些调用与Binder有关,以后学习 sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); LOGI("ServiceManager: %p\n", sm.get()); sp<GrimReaper> grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger. SurfaceFlinger服务在system_server进程中创建 SurfaceFlinger::instantiate(); } // Start the sensor service SensorService::instantiate(); // On the simulator, audioflinger et al don't get started the // same way as on the device, and we need to start them here if (!proc->supportsProcesses()) { // Start the AudioFlinger AudioFlinger::instantiate(); // Start the media playback service MediaPlayerService::instantiate(); // Start the camera service CameraService::instantiate(); // Start the audio policy service AudioPolicyService::instantiate(); } // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. LOGI("System server: starting Android runtime.\n"); //(f2)调用com.android.server.SystemServer类的init2函数 AndroidRuntime* runtime = AndroidRuntime::getRuntime(); LOGI("System server: starting Android services.\n"); runtime->callStatic("com/android/server/SystemServer", "init2"); //下面判断与Binder有关,以后学习 // If running in our own process, just go into the thread // pool. Otherwise, call the initialization finished // func to let this process continue its initilization. if (proc->supportsProcesses()) { LOGI("System server: entering thread pool.\n"); ProcessState::self()->startThreadPool(); //调用joinThreadPool后,当前线程也加入到Binder通信的大潮中。 IPCThreadState::self()->joinThreadPool(); LOGI("System server: exiting thread pool.\n"); } return NO_ERROR; }
总结:init1函数创建了一些系统服务,然后把调用线程加入到Binder通信中了。在这个过程中,还调用了init2函数。
(f2)分析init2函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); //(f3)启动一个ServerThread线程 }
(f3)分析ServerThread的run函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); BinderInternal.disableBackgroundScheduling(true); android.os.Process.setCanSelfBackground(false); // Check whether we failed to shut down last time we tried. { final String shutdownAction = SystemProperties.get( ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); if (shutdownAction != null && shutdownAction.length() > 0) { boolean reboot = (shutdownAction.charAt(0) == '1'); final String reason; if (shutdownAction.length() > 1) { reason = shutdownAction.substring(1, shutdownAction.length()); } else { reason = null; } ShutdownThread.rebootOrShutdown(reboot, reason); } } String factoryTestStr = SystemProperties.get("ro.factorytest"); int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF : Integer.parseInt(factoryTestStr); LightsService lights = null; PowerManagerService power = null; BatteryService battery = null; ConnectivityService connectivity = null; IPackageManager pm = null; Context context = null; WindowManagerService wm = null; BluetoothService bluetooth = null; BluetoothA2dpService bluetoothA2dp = null; HeadsetObserver headset = null; HookSwitchObserver hookSwitch = null; DockObserver dock = null; HdmiObserver hdmi = null; UsbService usb = null; UiModeManagerService uiMode = null; RecognitionManagerService recognition = null; ThrottleService throttle = null; UsbMonitor usbmon = null; // Critical services... try { Slog.i(TAG, "Entropy Service"); //启动Entropy Service ServiceManager.addService("entropy", new EntropyService()); //启动电源管理服务 Slog.i(TAG, "Power Manager"); power = new PowerManagerService(); ServiceManager.addService(Context.POWER_SERVICE, power); Slog.i(TAG, "Activity Manager"); context = ActivityManagerService.main(factoryTest); Slog.i(TAG, "Telephony Registry"); ServiceManager.addService("telephony.registry", new TelephonyRegistry(context)); AttributeCache.init(context); Slog.i(TAG, "Package Manager"); pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF); ActivityManagerService.setSystemProcess(); mContentResolver = context.getContentResolver(); // The AccountManager must come before the ContentService try { Slog.i(TAG, "Account Manager"); ServiceManager.addService(Context.ACCOUNT_SERVICE, new AccountManagerService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Account Manager", e); } Slog.i(TAG, "Content Manager"); ContentService.main(context, factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL); Slog.i(TAG, "System Content Providers"); ActivityManagerService.installSystemProviders(); //启动电池管理服务 Slog.i(TAG, "Battery Service"); battery = new BatteryService(context); ServiceManager.addService("battery", battery); Slog.i(TAG, "usb Service"); usbmon = new UsbMonitor(context); ServiceManager.addService("usbMon", usbmon); Slog.i(TAG, "Lights Service"); lights = new LightsService(context); Slog.i(TAG, "Vibrator Service"); ServiceManager.addService("vibrator", new VibratorService(context)); // only initialize the power service after we have started the // lights service, content providers and the battery service. power.init(context, lights, ActivityManagerService.getDefault(), battery); Slog.i(TAG, "Alarm Manager"); AlarmManagerService alarm = new AlarmManagerService(context); ServiceManager.addService(Context.ALARM_SERVICE, alarm); //初始化看门狗 Slog.i(TAG, "Init Watchdog"); Watchdog.getInstance().init(context, battery, power, alarm, ActivityManagerService.self()); //启动WindowManager服务 Slog.i(TAG, "Window Manager"); wm = WindowManagerService.main(context, power, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL); ServiceManager.addService(Context.WINDOW_SERVICE, wm); //启动ActivityManager服务 ((ActivityManagerService)ServiceManager.getService("activity")) .setWindowManager(wm); // Skip Bluetooth if we have an emulator kernel // TODO: Use a more reliable check to see if this product should // support Bluetooth - see bug 988521 if (SystemProperties.get("ro.kernel.qemu").equals("1")) { Slog.i(TAG, "Registering null Bluetooth Service (emulator)"); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null); } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { Slog.i(TAG, "Registering null Bluetooth Service (factory test)"); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null); } else { Slog.i(TAG, "Bluetooth Service"); bluetooth = new BluetoothService(context); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth); bluetooth.initAfterRegistration(); bluetoothA2dp = new BluetoothA2dpService(context, bluetooth); ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE, bluetoothA2dp); int bluetoothOn = Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_ON, 0); if (bluetoothOn > 0) { bluetooth.enable(); } } } catch (RuntimeException e) { Slog.e("System", "Failure starting core service", e); } DevicePolicyManagerService devicePolicy = null; StatusBarManagerService statusBar = null; InputMethodManagerService imm = null; AppWidgetService appWidget = null; NotificationManagerService notification = null; WallpaperManagerService wallpaper = null; LocationManagerService location = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { Slog.i(TAG, "Device Policy"); devicePolicy = new DevicePolicyManagerService(context); ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy); } catch (Throwable e) { Slog.e(TAG, "Failure starting DevicePolicyService", e); } try { Slog.i(TAG, "Status Bar"); statusBar = new StatusBarManagerService(context); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } catch (Throwable e) { Slog.e(TAG, "Failure starting StatusBarManagerService", e); } try { Slog.i(TAG, "Clipboard Service"); ServiceManager.addService(Context.CLIPBOARD_SERVICE, new ClipboardService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Clipboard Service", e); } try { Slog.i(TAG, "Input Method Service"); imm = new InputMethodManagerService(context, statusBar); ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm); } catch (Throwable e) { Slog.e(TAG, "Failure starting Input Manager Service", e); } try { Slog.i(TAG, "NetStat Service"); ServiceManager.addService("netstat", new NetStatService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting NetStat Service", e); } try { Slog.i(TAG, "NetworkManagement Service"); ServiceManager.addService( Context.NETWORKMANAGEMENT_SERVICE, NetworkManagementService.create(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting NetworkManagement Service", e); } try { Slog.i(TAG, "Connectivity Service"); connectivity = ConnectivityService.getInstance(context); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); } catch (Throwable e) { Slog.e(TAG, "Failure starting Connectivity Service", e); } try { Slog.i(TAG, "Throttle Service"); throttle = new ThrottleService(context); ServiceManager.addService( Context.THROTTLE_SERVICE, throttle); } catch (Throwable e) { Slog.e(TAG, "Failure starting ThrottleService", e); } try { Slog.i(TAG, "Accessibility Manager"); ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, new AccessibilityManagerService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Accessibility Manager", e); } try { /* * NotificationManagerService is dependant on MountService, * (for media / usb notifications) so we must start MountService first. */ Slog.i(TAG, "Mount Service"); ServiceManager.addService("mount", new MountService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Mount Service", e); } try { Slog.i(TAG, "Notification Manager"); notification = new NotificationManagerService(context, statusBar, lights); ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification); } catch (Throwable e) { Slog.e(TAG, "Failure starting Notification Manager", e); } try { Slog.i(TAG, "Device Storage Monitor"); ServiceManager.addService(DeviceStorageMonitorService.SERVICE, new DeviceStorageMonitorService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting DeviceStorageMonitor service", e); } try { Slog.i(TAG, "Location Manager"); location = new LocationManagerService(context); ServiceManager.addService(Context.LOCATION_SERVICE, location); } catch (Throwable e) { Slog.e(TAG, "Failure starting Location Manager", e); } try { Slog.i(TAG, "Search Service"); ServiceManager.addService(Context.SEARCH_SERVICE, new SearchManagerService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Search Service", e); } if (INCLUDE_DEMO) { Slog.i(TAG, "Installing demo data..."); (new DemoThread(context)).start(); } try { Slog.i(TAG, "DropBox Service"); ServiceManager.addService(Context.DROPBOX_SERVICE, new DropBoxManagerService(context, new File("/data/system/dropbox"))); } catch (Throwable e) { Slog.e(TAG, "Failure starting DropBoxManagerService", e); } try { Slog.i(TAG, "Wallpaper Service"); wallpaper = new WallpaperManagerService(context); ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper); } catch (Throwable e) { Slog.e(TAG, "Failure starting Wallpaper Service", e); } try { Slog.i(TAG, "Audio Service"); ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Audio Service", e); } try { Slog.i(TAG, "Headset Observer"); // Listen for wired headset changes headset = new HeadsetObserver(context); hookSwitch = new HookSwitchObserver(context); } catch (Throwable e) { Slog.e(TAG, "Failure starting HeadsetObserver", e); } try { Slog.i(TAG, "Hdmi Observer"); // Listen for hdmi changes hdmi = new HdmiObserver(context); } catch (Throwable e) { Slog.e(TAG, "Failure starting HdmiObserver", e); } try { Slog.i(TAG, "Dock Observer"); // Listen for dock station changes dock = new DockObserver(context, power); } catch (Throwable e) { Slog.e(TAG, "Failure starting DockObserver", e); } try { Slog.i(TAG, "USB Service"); // Listen for USB changes usb = new UsbService(context); ServiceManager.addService(Context.USB_SERVICE, usb); } catch (Throwable e) { Slog.e(TAG, "Failure starting UsbService", e); } try { Slog.i(TAG, "UI Mode Manager Service"); // Listen for UI mode changes uiMode = new UiModeManagerService(context); } catch (Throwable e) { Slog.e(TAG, "Failure starting UiModeManagerService", e); } try { Slog.i(TAG, "Backup Service"); ServiceManager.addService(Context.BACKUP_SERVICE, new BackupManagerService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Backup Service", e); } try { Slog.i(TAG, "AppWidget Service"); appWidget = new AppWidgetService(context); ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget); } catch (Throwable e) { Slog.e(TAG, "Failure starting AppWidget Service", e); } try { Slog.i(TAG, "Recognition Service"); recognition = new RecognitionManagerService(context); } catch (Throwable e) { Slog.e(TAG, "Failure starting Recognition Service", e); } try { Slog.i(TAG, "DiskStats Service"); ServiceManager.addService("diskstats", new DiskStatsService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting DiskStats Service", e); } } // make sure the ADB_ENABLED setting value matches the secure property value Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, "1".equals(SystemProperties.get("persist.service.adb.enable")) ? 1 : 0); // register observer to listen for settings changes mContentResolver.registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED), false, new AdbSettingsObserver()); // Before things start rolling, be sure we have decided whether // we are in safe mode. final boolean safeMode = wm.detectSafeMode(); if (safeMode) { try { ActivityManagerNative.getDefault().enterSafeMode(); // Post the safe mode state in the Zygote class Zygote.systemInSafeMode = true; // Disable the JIT for the system_server process VMRuntime.getRuntime().disableJitCompilation(); } catch (RemoteException e) { } } else { // Enable the JIT for the system_server process VMRuntime.getRuntime().startJitCompilation(); } // It is now time to start up the app processes... if (devicePolicy != null) { devicePolicy.systemReady(); } if (notification != null) { notification.systemReady(); } if (statusBar != null) { statusBar.systemReady(); } wm.systemReady(); power.systemReady(); try { pm.systemReady(); } catch (RemoteException e) { } // These are needed to propagate to the runnable below. final StatusBarManagerService statusBarF = statusBar; final BatteryService batteryF = battery; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; final UsbService usbF = usb; final ThrottleService throttleF = throttle; final UiModeManagerService uiModeF = uiMode; final AppWidgetService appWidgetF = appWidget; final WallpaperManagerService wallpaperF = wallpaper; final InputMethodManagerService immF = imm; final RecognitionManagerService recognitionF = recognition; final LocationManagerService locationF = location; final HookSwitchObserver hookSwitchF = hookSwitch; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. ((ActivityManagerService)ActivityManagerNative.getDefault()) .systemReady(new Runnable() { public void run() { Slog.i(TAG, "Making services ready"); if (statusBarF != null) statusBarF.systemReady2(); if (batteryF != null) batteryF.systemReady(); if (connectivityF != null) connectivityF.systemReady(); if (dockF != null) dockF.systemReady(); if (usbF != null) usbF.systemReady(); if (uiModeF != null) uiModeF.systemReady(); if (recognitionF != null) recognitionF.systemReady(); Watchdog.getInstance().start(); // It is now okay to let the various system services start their // third party code... if (appWidgetF != null) appWidgetF.systemReady(safeMode); if (wallpaperF != null) wallpaperF.systemReady(); if (immF != null) immF.systemReady(); if (locationF != null) locationF.systemReady(); if (throttleF != null) throttleF.systemReady(); if (hookSwitchF != null) hookSwitchF.systemReady(); } }); // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } Looper.loop(); //进行消息循环,然后处理消息。 Slog.d(TAG, "System ServerThread is exiting!"); } }
Init2函数就是单独创建了一个线程,用以启动系统的各项服务。
ps: Java世界的重要Service都在这里启动,所以SS非常重要!
关于SystemServer的总结,通过下图来展示过程。
SystemServer的调用流程
知识点3:zygote的分裂
通过ActivityManagerService来分析。
1. ActivityManagerService发送请求
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { if (app.pid > 0 && app.pid != MY_PID) { synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } app.pid = 0; } if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG, "startProcessLocked removing on hold: " + app); mProcessesOnHold.remove(app); updateCpuStats(); System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1); mProcDeaths[0] = 0; try { int uid = app.info.uid; int[] gids = null; try { gids = mContext.getPackageManager().getPackageGids( app.info.packageName); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Unable to retrieve gids", e); } if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) { if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL && mTopComponent != null && app.processName.equals(mTopComponent.getPackageName())) { uid = 0; } if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) { uid = 0; } } int debugFlags = 0; if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; } // Run the app in safe mode if its manifest requests so or the // system is booted in safe mode. if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || Zygote.systemInSafeMode == true) { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } if ("1".equals(SystemProperties.get("debug.checkjni"))) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } //(a) Process类(android.os.Process) int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null, uid, uid, gids, debugFlags, null); BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); synchronized (bs) { if (bs.isOnBattery()) { app.batteryStats.incStartsLocked(); } } EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid, app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); if (app.persistent) { Watchdog.getInstance().processStarted(app.processName, pid); } StringBuilder buf = mStringBuilder; buf.setLength(0); buf.append("Start proc "); buf.append(app.processName); buf.append(" for "); buf.append(hostingType); if (hostingNameStr != null) { buf.append(" "); buf.append(hostingNameStr); } buf.append(": pid="); buf.append(pid); buf.append(" uid="); buf.append(uid); buf.append(" gids={"); if (gids != null) { for (int gi=0; gi<gids.length; gi++) { if (gi != 0) buf.append(", "); buf.append(gids[gi]); } } buf.append("}"); Slog.i(TAG, buf.toString()); if (pid == 0 || pid == MY_PID) { // Processes are being emulated with threads. app.pid = MY_PID; app.removed = false; mStartingProcesses.add(app); } else if (pid > 0) { app.pid = pid; app.removed = false; synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(pid, app); Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT); } } else { app.pid = 0; RuntimeException e = new RuntimeException( "Failure starting process " + app.processName + ": returned pid=" + pid); Slog.e(TAG, e.getMessage(), e); } } catch (RuntimeException e) { // XXX do better error recovery. app.pid = 0; Slog.e(TAG, "Failure starting process " + app.processName, e); } }
(a) 分析Process类的start函数[---->Process.java]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Start a new process. * * <p>If processes are enabled, a new process is created and the * static main() function of a <var>processClass</var> is executed there. * The process will continue running after this function returns. * * <p>If processes are not enabled, a new thread in the caller's * process is created and main() of <var>processClass</var> called there. * * <p>The niceName parameter, if not an empty string, is a custom name to * give to the process instead of using processClass. This allows you to * make easily identifyable processes even if you are using the same base * <var>processClass</var> to start them. * * @param processClass The class to use as the process's main entry * point. * @param niceName A more readable name to use for the process. * @param uid The user-id under which the process will run. * @param gid The group-id under which the process will run. * @param gids Additional group-ids associated with the process. * @param enableDebugger True if debugging should be enabled for this process. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return int If > 0 the pid of the new process; if 0 the process is * being emulated by a thread * @throws RuntimeException on fatal start failure * * {@hide} */ public static final int start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, String[] zygoteArgs) { //其中,processClass的值是”android.os.ActivityThread”。 if (supportsProcesses()) { try { //(b) 调用startViaZygote函数 return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); } } else { // Running in single-process mode Runnable runnable = new Runnable() { public void run() { Process.invokeStaticMain(processClass); } }; // Thread constructors must not be called with null names (see spec). if (niceName != null) { new Thread(runnable, niceName).start(); } else { new Thread(runnable).start(); } return 0; } }
(b) 分析startViaZygote函数[---->Process.java]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* Starts a new process via the zygote mechanism. * * @param processClass Class name whose static main() to run * @param niceName 'nice' process name to appear in ps * @param uid a POSIX uid that the new process should setuid() to * @param gid a POSIX gid that the new process shuold setgid() to * @param gids null-ok; a list of supplementary group IDs that the * new process should setgroup() to. * @param enableDebugger True if debugging should be enabled for this process. * @param extraArgs Additional arguments to supply to the zygote process. * @return PID * @throws ZygoteStartFailedEx if process start failed for any reason */ private static int startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, String[] extraArgs) throws ZygoteStartFailedEx { int pid; synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); // --runtime-init, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-init"); //这个参数很重要 argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) { argsForZygote.add("--enable-safemode"); } if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) { argsForZygote.add("--enable-debugger"); } if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) { argsForZygote.add("--enable-checkjni"); } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } //TODO optionally enable debuger //argsForZygote.add("--enable-debugger"); // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } //(c) 之前做一些参数的处理,最后调用zygoteSendArgsAndGetPid函数 pid = zygoteSendArgsAndGetPid(argsForZygote); } if (pid <= 0) { throw new ZygoteStartFailedEx("zygote start failed:" + pid); } return pid; }
(c) 分析zygoteSendArgsAndGetPid函数[---->Process.java]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Sends an argument list to the zygote process, which starts a new child * and returns the child's pid. Please note: the present implementation * replaces newlines in the argument list with spaces. * @param args argument list * @return PID of new child process * @throws ZygoteStartFailedEx if process start failed for any reason */ private static int zygoteSendArgsAndGetPid(ArrayList<String> args) throws ZygoteStartFailedEx { int pid; //(d) 根据字面意思,是否是打开了和Zygote通信的socket呢? openZygoteSocketIfNeeded(); try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure. */ //把请求的参数发送到Zygote sZygoteWriter.write(Integer.toString(args.size())); sZygoteWriter.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } sZygoteWriter.write(arg); sZygoteWriter.newLine(); } //读取Zygote处理完的结果,就可以知道某个进程的pid了! sZygoteWriter.flush(); // Should there be a timeout on this? pid = sZygoteInputStream.readInt(); if (pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } } catch (IOException ex) { try { if (sZygoteSocket != null) { sZygoteSocket.close(); } } catch (IOException ex2) { // we're going to fail anyway Log.e(LOG_TAG,"I/O exception on routine close", ex2); } sZygoteSocket = null; throw new ZygoteStartFailedEx(ex); } return pid; }
(d) 分析openZygoteSocketIfNeeded函数[---->Process.java]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Tries to open socket to Zygote process if not already open. If * already open, does nothing. May block and retry. */ private static void openZygoteSocketIfNeeded() throws ZygoteStartFailedEx { int retryCount; if (sPreviousZygoteOpenFailed) { /* * If we've failed before, expect that we'll fail again and * don't pause for retries. */ retryCount = 0; } else { retryCount = 10; } /* * See bug #811181: Sometimes runtime can make it up before zygote. * Really, we'd like to do something better to avoid this condition, * but for now just wait a bit... */ for (int retry = 0 ; (sZygoteSocket == null) && (retry < (retryCount + 1)) ; retry++ ) { if (retry > 0) { try { Log.i("Zygote", "Zygote not up yet, sleeping..."); Thread.sleep(ZYGOTE_RETRY_MILLIS); } catch (InterruptedException ex) { // should never happen } } try { //果真如此,打开了和Zygote通信的Socket!!! sZygoteSocket = new LocalSocket(); sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED)); sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream()); sZygoteWriter = new BufferedWriter( new OutputStreamWriter( sZygoteSocket.getOutputStream()), 256); Log.i("Zygote", "Process: zygote socket opened"); sPreviousZygoteOpenFailed = false; break; } catch (IOException ex) { if (sZygoteSocket != null) { try { sZygoteSocket.close(); } catch (IOException ex2) { Log.e(LOG_TAG,"I/O exception on close after exception", ex2); } } sZygoteSocket = null; } } if (sZygoteSocket == null) { sPreviousZygoteOpenFailed = true; throw new ZygoteStartFailedEx("connect failed"); } }
总结1:由此,ActivityManagerService就向Zygote发送请求了。从startProcessLocked函数中得知,发送的请求的参数中有一个字符串,其值为”android.app.ActivityThread”。因此,回到zygote处理请求的源码中去。
2.有求必应之响应请求(与之前一节的”有求必应之等待请求”遥相呼应)
回顾”有求必应之等待请求”,回到ZygoteInit.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time. * * @throws MethodAndArgsCaller in a child process when a main() should * be executed. */ private static void runSelectLoopMode() throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList(); ArrayList<ZygoteConnection> peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; /* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ 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; //(e) 调用ZygoteConnection的runOnce函数 done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }
每当有请求数据发送过来时,zygote就会调用ZygoteConnection的runOnce函数。
(e) 分析runOnce函数[---->ZygoteConnection.java]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Reads one start command from the command socket. If successful, * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller} * exception is thrown in that child while in the parent process, * the method returns normally. On failure, the child is not * spawned and messages are printed to the log and stderr. Returns * a boolean status value indicating whether an end-of-file on the command * socket has been encountered. * * @return false if command socket should continue to be read from, or * true if an end-of-file has been encountered. * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main() * method in child process */ boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; try { args = readArgumentList(); //读取SS发送过来的参数 descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { Log.w(TAG, "IOException on command socket " + ex.getMessage()); closeSocket(); return true; } if (args == null) { // EOF reached. closeSocket(); return true; } /** the stderr of the most recent request, if avail */ PrintStream newStderr = null; if (descriptors != null && descriptors.length >= 3) { newStderr = new PrintStream( new FileOutputStream(descriptors[2])); } int pid; try { parsedArgs = new Arguments(args); applyUidSecurityPolicy(parsedArgs, peer); applyDebuggerSecurityPolicy(parsedArgs); applyRlimitSecurityPolicy(parsedArgs, peer); applyCapabilitiesSecurityPolicy(parsedArgs, peer); int[][] rlimits = null; if (parsedArgs.rlimits != null) { rlimits = parsedArgs.rlimits.toArray(intArray2d); } //从字面意思可知,Zygote又分裂出了一个子进程。 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits); } catch (IllegalArgumentException ex) { logAndPrintError (newStderr, "Invalid zygote arguments", ex); pid = -1; } catch (ZygoteSecurityException ex) { logAndPrintError(newStderr, "Zygote security policy prevents request: ", ex); pid = -1; } if (pid == 0) { //(f) 子进程处理,它就是我们要创建的Activity对应的子进程 handleChildProc(parsedArgs, descriptors, newStderr); // should never happen return true; } else { /* pid != 0 */ // in parent...pid of < 0 means failure //zygote进程 return handleParentProc(pid, descriptors, parsedArgs); } }
(f) 分析handleChildProc函数[---->ZygoteConnection.java]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Handles post-fork setup of child proc, closing sockets as appropriate, * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller * if successful or returning if failed. * * @param parsedArgs non-null; zygote args * @param descriptors null-ok; new file descriptors for stdio if available. * @param newStderr null-ok; stream to use for stderr until stdio * is reopened. * * @throws ZygoteInit.MethodAndArgsCaller on success to * trampoline to code that invokes static main. */ private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { /* * Close the socket, unless we're in "peer wait" mode, in which * case it's used to track the liveness of this process. */ if (parsedArgs.peerWait) { try { ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true); sPeerWaitSocket = mSocket; } catch (IOException ex) { Log.e(TAG, "Zygote Child: error setting peer wait " + "socket to be close-on-exec", ex); } } else { closeSocket(); ZygoteInit.closeServerSocket(); } if (descriptors != null) { try { ZygoteInit.reopenStdio(descriptors[0], descriptors[1], descriptors[2]); for (FileDescriptor fd: descriptors) { ZygoteInit.closeDescriptor(fd); } newStderr = System.err; } catch (IOException ex) { Log.e(TAG, "Error reopening stdio", ex); } } //SS发来的参数中有”--runtime-init”,所以parsedArgs.runtimeInit为true if (parsedArgs.runtimeInit) { RuntimeInit.zygoteInit(parsedArgs.remainingArgs); // (g) } else { ClassLoader cloader; if (parsedArgs.classpath != null) { cloader = new PathClassLoader(parsedArgs.classpath, ClassLoader.getSystemClassLoader()); } else { cloader = ClassLoader.getSystemClassLoader(); } String className; try { className = parsedArgs.remainingArgs[0]; } catch (ArrayIndexOutOfBoundsException ex) { logAndPrintError (newStderr, "Missing required class name argument", null); return; } String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1]; System.arraycopy(parsedArgs.remainingArgs, 1, mainArgs, 0, mainArgs.length); try { ZygoteInit.invokeStaticMain(cloader, className, mainArgs); } catch (RuntimeException ex) { logAndPrintError (newStderr, "Error starting. ", ex); } } }
(g) 分析RuntimeInit.zygoteInit函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * The main function called when started through the zygote process. This * could be unified with main(), if the native code in finishInit() * were rationalized with Zygote startup.<p> * * Current recognized args: * <ul> * <li> --nice-name=<i>nice name to appear in ps</i> * <li> <code> [--] <start class name> <args> * </ul> * * @param argv arg strings */ public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller { // TODO: Doing this here works, but it seems kind of arbitrary. Find // a better place. The goal is to set it up for applications, but not // tools like am. //重定向标准输出和错误输出 System.setOut(new AndroidPrintStream(Log.INFO, "System.out")); System.setErr(new AndroidPrintStream(Log.WARN, "System.err")); commonInit(); // zygoteInitNative函数最终会调用AppRuntime的onZygoteInit函数,在那个函数中建立了和Binder的关系。 zygoteInitNative(); int curArg = 0; for ( /* curArg */ ; curArg < argv.length; curArg++) { String arg = argv[curArg]; if (arg.equals("--")) { curArg++; break; } else if (!arg.startsWith("--")) { break; } else if (arg.startsWith("--nice-name=")) { String niceName = arg.substring(arg.indexOf('=') + 1); Process.setArgV0(niceName); } } if (curArg == argv.length) { Slog.e(TAG, "Missing classname argument to RuntimeInit!"); // let the process exit return; } // Remaining arguments are passed to the start class's static main String startClass = argv[curArg++]; String[] startArgs = new String[argv.length - curArg]; System.arraycopy(argv, curArg, startArgs, 0, startArgs.length); invokeStaticMain(startClass, startArgs); //之前已经介绍过了 }
Zygote分裂子进程后,自己将在handleParentProc中做一些扫尾工作,然后继续等待请求进行下一次分裂。
ps:这个android.app.ActivityThread类,实际上是Android中apk程序所对应的进程,它的main方法就是apk程序的main函数。
这一节的分析,也可以看出来,Android系统上运行的apk程序,其父进程都是zygote。可通过adb shell 登陆后,用ps查看。
Zygote总结:
Zygote的分裂是由SS控制的,过程用图描述如下:
关于ActivityThread的详细分析,可参考
Android核心分析(21)----Android应用框架之AndroidApplication