《深入理解Android(卷1)》笔记 4.第四章 深入理解zygote
2012-12-17 10:19 ...平..淡... 阅读(1990) 评论(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方法分析
app_main::main
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方法。分析该方法:
AndroidRuntime.cpp::start
/*
* 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方法创建虚拟机,代码如下:
AndroidRuntime::startVm
/*
* 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方式实现,所以需要提前注册这些函数。
代码如下:
AndroidRuntime::startReg
/*
* 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).代码如下:
register_jni_procs
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) { //调用数组元素的mProc函数
#ifndef NDEBUG
LOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
可以看出,这个函数主要调用的就是数组中的mProc函数。因此接下来需要分析数组和mProc函数。
(2.2)先分析数组(RegJNIRec类型,数组名为gRegJNI)
RegJNIRec数组
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))
ZygoteInit::main
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()
preloadClasses
/ * 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()
preloadResources
/**
* 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。见代码:
registerZygoteSocket
/**
* 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⊙))
分析源码:
startSystemServer
/**
* 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函数---->有求必应之等待请求
runSelectLoopMode
/**
* 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中)。
dalvik_system_Zygote::Dalvik_dalvik_system_Zygote_forkSystemServer
/* 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函数。代码如下:
dalvik_system_Zygote::forkAndSpecializeCommon
/*
* 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()函数。代码如下:
dalvik_system_Zygote::setSignalHandler
/*
* 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函数。
dalvik_system_Zygote::sigchldHandler
/*
* 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函数。
ZygoteInit::handleSystemServerProcess
/**
* 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函数中,分析代码:
RuntimeInit::zygoteInit
/**
* 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类的构造函数
AndroidRuntime::AndroidRuntime()
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会做些什么呢?分析如下代码:
onZygoteInit
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函数分析
invokeStaticMain
/**
* 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中。代码如下:
MethodAndArgsCaller::run()
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函数:
SystemServer::main
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中实现。代码如下:
android_server_SystemServer_init1
extern "C" int system_init();
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
system_init(); //(f1)调用该函数。
}
(f1)system_init的实现在system_init.cpp中,代码如下:
system_init()
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函数
init2()
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函数
ServerThread::run()
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发送请求
startProcessLocked()
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]
Process.java::start()
/** * 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]
Process.java::startViaZygote()
/* 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]
Process.java::zygoteSendArgsAndGetPid()
/** * 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]
Process.java::openZygoteSocketIfNeeded()
/** * 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
ZygoteInit.java::runSelectLoopMode()
/** * 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]
ZygoteConnection.java::runOnce()
/** * 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]
ZygoteConnection.java::handleChildProc()
/** * 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函数
RuntimeInit.java::zygoteInit()
/** * 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
app_main::main
浙公网安备 33010602011771号