Android(安卓)Zygote分析
Zygote 是Android第一个应用进程,它由init程序解析import /init.${ro.zygote}.rc 所启动。
ro.zygote32.rc
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 writepid /dev/cpuset/foreground/tasks
看到它的启动由app_process 执行文件启动,接下来分析app_process源码:frameworks/base/cmds/app_process/app_main.cpp,直接看其的main函数
Vector args; if (!className.isEmpty()) { args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { // We're in zygote mode. maybeCreateDalvikCache(); if (startSystemServer) { args.add(String8("start-system-server")); } char prop[PROP_VALUE_MAX]; if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY); return 11; } String8 abiFlag("--abi-list="); abiFlag.append(prop); args.add(abiFlag); // In zygote mode, pass all remaining arguments to the zygote // main() method. for (; i < argc; ++i) { args.add(String8(argv[i])); } } if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string()); set_process_name(niceName.string()); } if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); bool debug = false; if (debug) { ALOGD("app_process pid:%d, ppid:%d.", getpid(), getppid()); String8 cmd; for (int i = 0; i < argc; i++) { cmd.append(argv[i]); if (i < argc -1) { cmd.append(" "); } } ALOGD("app_process %s.", cmd.string()); FILE* processF = popen("ps >> /data/system/app_process.txt;", "r"); if (processF) { pclose(processF); } } } 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; }
通过解析启动参数,判断是否启动Zygote程序自身或者其他进程,是否需要启动SystemServer进程。Ps: else if 条件分支处系我加的日志。
无论启动的是否为zygote,都执行了Runtime.start函数(frameworks/base/core/jni/AndroidRuntime.cpp 中的start函数),该函数的核心是启动虚拟机实例,并注册androidAPI基础类中的所以native函数,并且反射ZygoteInit类的main函数。
/* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env); if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; }
现在看启动虚拟机实例的startVM函数
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote){ JavaVMInitArgs initArgs; char propBuf[PROPERTY_VALUE_MAX]; char stackTraceFileBuf[sizeof("-Xstacktracefile:")-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 usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX]; char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX]; char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX]; char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX]; char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX]; char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX]; char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX]; char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX]; char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX]; char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX]; char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX]; char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX]; char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX]; char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX]; char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX]; char dex2oat_isa_variant_key[PROPERTY_KEY_MAX]; char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX]; char dex2oat_isa_features_key[PROPERTY_KEY_MAX]; char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX]; char dex2oatFlagsBuf[PROPERTY_VALUE_MAX]; char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX]; char extraOptsBuf[PROPERTY_VALUE_MAX]; char voldDecryptBuf[PROPERTY_VALUE_MAX]; enum { kEMDefault, kEMIntPortable, kEMIntFast, kEMJitCompiler, } executionMode = kEMDefault; char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX]; char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX]; char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX]; char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX]; char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX]; char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 + PROPERTY_VALUE_MAX]; char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX]; char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + PROPERTY_VALUE_MAX]; char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX]; char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX]; char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX]; char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX]; char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX]; char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX]; char fingerprintBuf[sizeof("-Xfingerprint:") + PROPERTY_VALUE_MAX]; bool checkJni = false; 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; } } ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF"); if (checkJni) { /* extended JNI checking */ addOption("-Xcheck:jni"); /* with -Xcheck:jni, this provides a JNI function call trace */ //addOption("-verbose:jni"); } 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; } parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:"); strcpy(jniOptsBuf, "-Xjniopts:"); if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) { ALOGI("JNI options: '%s'\n", jniOptsBuf); } /* route exit() to our handler */ addOption("exit", (void*) runtime_exit); /* route fprintf() to our handler */ addOption("vfprintf", (void*) runtime_vfprintf); /* register the framework-specific "is sensitive thread" hook */ addOption("sensitiveThread", (void*) runtime_isSensitiveThread); /* enable verbose; standard options are { jni, gc, class } */ //addOption("-verbose:jni"); addOption("-verbose:gc"); //addOption("-verbose:class"); /* * The default starting and maximum size of the heap. Larger * values should be specified in a product property override. */ parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m"); parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m"); parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit="); parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree="); parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree="); parseRuntimeOption("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization="); /* * JIT related options. */ parseRuntimeOption("dalvik.vm.usejit", usejitOptsBuf, "-Xusejit:"); parseRuntimeOption("dalvik.vm.jitcodecachesize", jitcodecachesizeOptsBuf, "-Xjitcodecachesize:"); parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:"); property_get("ro.config.low_ram", propBuf, ""); if (strcmp(propBuf, "true") == 0) { addOption("-XX:LowMemoryMode"); } parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:"); parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC="); /* * Enable debugging only for apps forked from zygote. * Set suspend=y to pause during VM init and use android ADB transport. */ if (zygote) { addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y"); } parseRuntimeOption("dalvik.vm.lockprof.threshold", lockProfThresholdBuf, "-Xlockprofthreshold:"); if (executionMode == kEMIntPortable) { addOption("-Xint:portable"); } else if (executionMode == kEMIntFast) { addOption("-Xint:fast"); } else if (executionMode == kEMJitCompiler) { addOption("-Xint:jit"); } // If we are booting without the real /data, don't spend time compiling. property_get("vold.decrypt", voldDecryptBuf, ""); bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) || (strcmp(voldDecryptBuf, "1") == 0)); // Extra options for boot.art/boot.oat image generation. parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf, "-Xms", "-Ximage-compiler-option"); parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf, "-Xmx", "-Ximage-compiler-option"); if (skip_compilation) { addOption("-Ximage-compiler-option"); addOption("--compiler-filter=verify-none"); } else { parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf, "--compiler-filter=", "-Ximage-compiler-option"); } // Make sure there is a preloaded-classes file. if (!hasFile("/system/etc/preloaded-classes")) { ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n", strerror(errno)); return -1; } addOption("-Ximage-compiler-option"); addOption("--image-classes=/system/etc/preloaded-classes"); // If there is a compiled-classes file, push it. if (hasFile("/system/etc/compiled-classes")) { addOption("-Ximage-compiler-option"); addOption("--compiled-classes=/system/etc/compiled-classes"); } property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, ""); parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option"); // Extra options for DexClassLoader. parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf, "-Xms", "-Xcompiler-option"); parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf, "-Xmx", "-Xcompiler-option"); if (skip_compilation) { addOption("-Xcompiler-option"); addOption("--compiler-filter=verify-none"); // We skip compilation when a minimal runtime is brought up for decryption. In that case // /data is temporarily backed by a tmpfs, which is usually small. // If the system image contains prebuilts, they will be relocated into the tmpfs. In this // specific situation it is acceptable to *not* relocate and run out of the prebuilts // directly instead. addOption("--runtime-arg"); addOption("-Xnorelocate"); } else { parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf, "--compiler-filter=", "-Xcompiler-option"); } parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option"); parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j", "-Ximage-compiler-option"); // The runtime will compile a boot image, when necessary, not using installd. Thus, we need to // pass the instruction-set-features/variant as an image-compiler-option. // TODO: Find a better way for the instruction-set.#if defined(__arm__) constexpr const char* instruction_set = "arm";#elif defined(__aarch64__) constexpr const char* instruction_set = "arm64";#elif defined(__mips__) && !defined(__LP64__) constexpr const char* instruction_set = "mips";#elif defined(__mips__) && defined(__LP64__) constexpr const char* instruction_set = "mips64";#elif defined(__i386__) constexpr const char* instruction_set = "x86";#elif defined(__x86_64__) constexpr const char* instruction_set = "x86_64";#else constexpr const char* instruction_set = "unknown";#endif // Note: it is OK to reuse the buffer, as the values are exactly the same between // * compiler-option, used for runtime compilation (DexClassLoader) // * image-compiler-option, used for boot-image compilation on device // Copy the variant. sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set); parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant, "--instruction-set-variant=", "-Ximage-compiler-option"); parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant, "--instruction-set-variant=", "-Xcompiler-option"); // Copy the features. sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set); parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features, "--instruction-set-features=", "-Ximage-compiler-option"); parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features, "--instruction-set-features=", "-Xcompiler-option"); property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, ""); parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option"); /* extra options; parse this late so it overrides others */ property_get("dalvik.vm.extra-opts", extraOptsBuf, ""); parseExtraOpts(extraOptsBuf, NULL); /* Set the properties for locale */ { strcpy(localeOption, "-Duser.locale="); const std::string locale = readLocale(); strncat(localeOption, locale.c_str(), PROPERTY_VALUE_MAX); addOption(localeOption); } /* * Set profiler options */ // Whether or not the profiler should be enabled. property_get("dalvik.vm.profiler", propBuf, "0"); if (propBuf[0] == '1') { addOption("-Xenable-profiler"); } // Whether the profile should start upon app startup or be delayed by some random offset // (in seconds) that is bound between 0 and a fixed value. property_get("dalvik.vm.profile.start-immed", propBuf, "0"); if (propBuf[0] == '1') { addOption("-Xprofile-start-immediately"); } // Number of seconds during profile runs. parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:"); // Length of each profile run (seconds). parseRuntimeOption("dalvik.vm.profile.duration-secs", profileDuration, "-Xprofile-duration:"); // Polling interval during profile run (microseconds). parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:"); // Coefficient for period backoff. The the period is multiplied // by this value after each profile run. parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:"); // Top K% of samples that are considered relevant when // deciding if the app should be recompiled. parseRuntimeOption("dalvik.vm.profile.top-k-thr", profileTopKThreshold, "-Xprofile-top-k-threshold:"); // The threshold after which a change in the structure of the // top K% profiled samples becomes significant and triggers // recompilation. A change in profile is considered // significant if X% (top-k-change-threshold) of the top K% // (top-k-threshold property) samples has changed. parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr", profileTopKChangeThreshold, "-Xprofile-top-k-change-threshold:"); // Type of profile data. parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:"); // Depth of bounded stack data parseRuntimeOption("dalvik.vm.profile.stack-depth", profileMaxStackDepth, "-Xprofile-max-stack-depth:"); /* * Tracing options. */ property_get("dalvik.vm.method-trace", propBuf, "false"); if (strcmp(propBuf, "true") == 0) { addOption("-Xmethod-trace"); parseRuntimeOption("dalvik.vm.method-trace-file", methodTraceFileBuf, "-Xmethod-trace-file:"); parseRuntimeOption("dalvik.vm.method-trace-file-siz", methodTraceFileSizeBuf, "-Xmethod-trace-file-size:"); property_get("dalvik.vm.method-trace-stream", propBuf, "false"); if (strcmp(propBuf, "true") == 0) { addOption("-Xmethod-trace-stream"); } } // Native bridge library. "0" means that native bridge is disabled. property_get("ro.dalvik.vm.native.bridge", propBuf, ""); if (propBuf[0] == '\0') { ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty"); } else if (strcmp(propBuf, "0") != 0) { snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX, "-XX:NativeBridge=%s", propBuf); addOption(nativeBridgeLibrary); }#if defined(__LP64__) const char* cpu_abilist_property_name = "ro.product.cpu.abilist64";#else const char* cpu_abilist_property_name = "ro.product.cpu.abilist32";#endif // defined(__LP64__) property_get(cpu_abilist_property_name, propBuf, ""); if (propBuf[0] == '\0') { ALOGE("%s is not expected to be empty", cpu_abilist_property_name); return -1; } snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf); addOption(cpuAbiListBuf); // Dalvik-cache pruning counter. parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf, "-Xzygote-max-boot-retry="); /* * When running with debug.generate-debug-info, add --generate-debug-info to * the compiler options so that the boot image, if it is compiled on device, * will include native debugging information. */ property_get("debug.generate-debug-info", propBuf, ""); if (strcmp(propBuf, "true") == 0) { addOption("-Xcompiler-option"); addOption("--generate-debug-info"); addOption("-Ximage-compiler-option"); addOption("--generate-debug-info"); } /* * Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will * contain the fingerprint and can be parsed. */ parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:"); 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. */ if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); return -1; } return 0;}
函数这么长,挑拣几个重要的描述:
dalvik.vm.checkjni:检测jni选项,会影响jni运行速度
dalvik.vm.execution-mode:虚拟机解释器模式:可移植、快速解释、即时编译Just-in-time
dalvik.vm.stack-trace-file:虚拟机traces文件路径,如果应用程序anr无响应会生成此文件,通常为/data/anr/traces.txt
dalvik.vm.heapstartsize:虚拟机堆内存启动大小
dalvik.vm.heapsize:虚拟机堆大小
dalvik.vm.heapgrowthlimit:堆大小增长限制大小
dalvik.vm.heapminfree/dalvik.vm.heapmaxfree:最小最大堆空闲大小
ro.dalvik.vm.native.bridge:native代码转换桥库,通常在模拟器会有值
其他的就不说明了(看不懂)
解析解析完这些参数开始启动虚拟机了
通过读取persist.sys.dalvik.vm.lib.2的内容判断启动的是dalvik虚拟机还是art虚拟机。
虚拟机启动完成之后开始反射ZygoteInitJava类的main函数
public static void main(String argv[]) { try { RuntimeInit.enableDdms(); // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } registerZygoteSocket(socketName);//创建ZygoteSocket EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload();//加载预加载的类,资源,共享库等 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gcAndFinalize();//释放且回收一次内存 // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false); if (startSystemServer) { //是否启动系统服务 startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList);//开始不断的轮询,等待ams到进程创建消息来fork子进程 closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }
通过之前传递的参数可得知需要启动SystemServer,
long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, 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 ); /* 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,1021,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", };
这是参数属性,足以让SystemServer掌控整个android系统(天命之子)。
关注到args最后一个参数,后续肯定会执行SystemServer来启动android所有服务。这时Zygote.forkSystemServer 将创建名为system_server的进程并将com.android.server.SystemServer传给system_server作为启动类。
接下来执行在system_server的函数handleSystemServerProcess将会被执行到,handleSystemServerProcess将会调用RuntimeInit.java的zygoteInit方法
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); redirectLogStreams(); //重定向System.out/err 内容到Log设备 commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); }
applicationInit(targetSdkVersion, argv, classLoader); //开始真正的调用SystemServer中的main函数,这是它的任务已经完成。
之前app_process除了能启动Zygote还可以启动其他应用程序
直接查看RuntimeInit的main函数
public static final void main(String[] argv) { enableDdms(); if (argv.length == 2 && argv[1].equals("application")) { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application"); redirectLogStreams(); } else { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool"); } commonInit(); /* * Now that we're running in interpreted code, call back into native code * to run the system. */ nativeFinishInit(); if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!"); }
如果是应用,需要重定向System.err/out流到Log设备,commonInit()是时区和http代理到设置等。nativeFinishInit()最终将通过jni调用
/* * Code written in the Java Programming Language calls here from main(). */static void com_android_internal_os_RuntimeInit_nativeFinishInit(JNIEnv* env, jobject clazz){ gCurRuntime->onStarted();}
回到app_main.cpp到虚函数onStarted中。
virtual void onStarted() { sp proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); AndroidRuntime* ar = AndroidRuntime::getRuntime(); ar->callMain(mClassName, mClass, mArgs); IPCThreadState::self()->stopProcess(); }
这里调用需要ProcessState来进程binder通讯,直到当前进main函数执行完毕之后才停止进程。常见到使用场景有am,pm 等文件
#!/system/bin/sh## Script to start "am" on the device, which has a very rudimentary# shell.#base=/systemexport CLASSPATH=$base/framework/am.jarexec app_process $base/bin com.android.commands.am.Am "$@"ps >> /data/misc/logd/record.ps //加到调试日志,忽略。
至此整个Zygote分析完成。
更多相关文章
- Android下openGL操作矩阵的函数
- 简单android Service 创建与启动示例
- Android得到视频缩略图
- android system services startup process
- Android中的设计模式--建造者模式
- android开机自启动的后台Service的实现 .
- Android(安卓)启动 Launcher
- android:获取已经安装软件列表
- 箭头函数的基础使用