您的位置:首页 > 编程语言

Zygote进程启动过程的源代码分析

2012-11-21 11:30 387 查看
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,zygote和system_server分别是Java世界的半边天,任何一个进程的死亡都会导致Java崩溃。

zygote本身是Native应用程序,与驱动内核无关。zygote最初的名字叫“app_process”,这个名字在Android.mk文件中指定,但在运行过程中被替换为"zygote"。

我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中:

1.system/core/rootdir/init.rc:

[java] view
plaincopy

//关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

//socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的

socket zygote stream 666

critical

onrestart write /sys/android_power/request_state wake

onrestart write /sys/power/state on

onrestart restart media

onrestart restart netd

onrestart restart mlistener

2.App_main.cpp

[java] view
plaincopy

int main(int argc, const char* const argv[])

{

//zygote 是由init进程fork而来,init.rc文件中为zygote进程设置的启动参数如下

//argc = 4

//argv = [-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--; // mArgLen = 48

AppRuntime runtime;

const char *arg;

const char *argv0;

argv0 = argv[0]; //-Xzygote

// Process command line arguments

// ignore argv[0]

argc--;

argv++;

//添加虚拟机参数选项

//addVmArguments(3, [/system/bin, --zygote, --start-system-server])结果返回 i=0

int i = runtime.addVmArguments(argc, argv);

// 设置虚拟机运行目录

if (i < argc) {

runtime.mParentDir = argv[i++]; //runtime.mParentDir =/system/bin

}

// i=1

// Next arg is startup classname or "--zygote"

if (i < argc) {

arg = argv[i++]; //arg = --zygote

//i=2

if (0 == strcmp("--zygote", arg)) {

//startSystemServer = true

bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false;

//设置argv0 的值为"zygote"

setArgv0(argv0, "zygote");

//设置进程名字

set_process_name("zygote");

// do last shutdown check

doLastShutDownCheck();

//调用Runtimed的start函数启动SystemServer进程,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;

}

}

这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。AppRuntime类的声明和实现在App_main.cpp中,派生于AndroidRuntime类

3.AndroidRuntime.cpp

[java] view
plaincopy

void AndroidRuntime::start(const char* className, const bool startSystemServer)

{

//className = "com.android.internal.os.ZygoteInit"

//startSystemServer = true

LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",className != NULL ? className : "(unknown)");

char* slashClassName = NULL;

char* cp;

JNIEnv* env;

blockSigpipe();

/*

* 'startSystemServer == true' means runtime is obslete and not run from

* init.rc anymore, so we print out the boot start event here.

*/

if (startSystemServer) {

/* track our progress through the boot sequence */

const int LOG_BOOT_PROGRESS_START = 3000;

LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

}

//获取环境变量android_root的根目录

const char* rootDir = getenv("ANDROID_ROOT");

if (rootDir == NULL) {

rootDir = "/system"; //如果获取结果为Null,则设置为"/system"

if (!hasDir("/system")) {

LOG_FATAL("No root directory specified, and /android does not exist.");

goto bail;

}

setenv("ANDROID_ROOT", rootDir, 1);//重新设置环境变量ANDROID_ROOT

}

//const char* kernelHack = getenv("LD_ASSUME_KERNEL");

//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

/* 启动虚拟机 */

if (startVm(&mJavaVM, &env) != 0)

goto bail;

/*

* 注册JNI函数

*/

if (startReg(env) < 0) {

LOGE("Unable to register all android natives\n");

goto bail;

}

/*

* We want to call main() with a String array with arguments in it.

* At present we only have one argument, the class name. Create an

* array to hold it.

*/

jclass stringClass;

jobjectArray strArray;

jstring classNameStr;

jstring startSystemServerStr;

//通过JNI查找java的java.lang.String类

stringClass = env->FindClass("java/lang/String");

assert(stringClass != NULL);

//创建字符串数组String strArray[] = new String[2];

strArray = env->NewObjectArray(2, stringClass, NULL);

assert(strArray != NULL);

//创建字符串classNameStr = new String("com.android.internal.os.ZygoteInit")

classNameStr = env->NewStringUTF(className);

assert(classNameStr != NULL);

//设置字符串数组元素strArray[0]="com.android.internal.os.ZygoteInit"

env->SetObjectArrayElement(strArray, 0, classNameStr);

//创建字符串startSystemServerStr= new String("true")

startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");

//设置字符串数组元素strArray[1]="true"

env->SetObjectArrayElement(strArray, 1, startSystemServerStr);

/*

* Start VM. This thread becomes the main thread of the VM, and will

* not return until the VM exits.

*/

jclass startClass;

jmethodID startMeth;

//将字符串className 复制到slashClassName

slashClassName = strdup(className);

//为符合JNI规范,将com.android.internal.os.ZygoteInit中的.换成/,变为slashClassName = com/android/internal/os/ZygoteInit

for (cp = slashClassName; *cp != '\0'; cp++)

if (*cp == '.')

*cp = '/';

//查找Java类com/android/internal/os/ZygoteInit

startClass = env->FindClass(slashClassName);

if (startClass == NULL) {

LOGE("JavaVM unable to locate class '%s'\n", slashClassName);

/* keep going */

} else {

//找到ZygoteInit类的静态main方法的jMethodID

startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");

if (startMeth == NULL) {

LOGE("JavaVM unable to find main() in '%s'\n", className);

/* keep going */

} else {

//通过JNI调用ZygoteInit类的main函数,传递的参数为:

//startClass = ZygoteInit

//startMeth = main

//strArray =["com.android.internal.os.ZygoteInit","true"]

//在调用ZygoteInit类的main方法后,zygote就进入了java世界

env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0

if (env->ExceptionCheck())

threadExitUncaughtException(env);

#endif

}

}

LOGD("Shutting down VM\n");

if (mJavaVM->DetachCurrentThread() != JNI_OK)

LOGW("Warning: unable to detach main thread\n");

if (mJavaVM->DestroyJavaVM() != 0)

LOGW("Warning: VM did not shut down cleanly\n");

bail:

free(slashClassName);

}

这个函数的作用是启动Android系统运行时库,它主要做了三件事情:

一是调用函数startVM启动虚拟机;

二是调用函数startReg注册JNI方法;

三是调用了com.android.internal.os.ZygoteInit类的main函数;

4.AndroidRuntime.cpp 启动虚拟机

[java] view
plaincopy

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 heapsizeOptsBuf[sizeof("-Xmx")-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,

#if defined(WITH_JIT)

kEMJitCompiler,

#endif

} executionMode = kEMDefault;

property_get("dalvik.vm.checkjni", propBuf, ""); //读取"dalvik.vm.checkjni"属性值,“true” : “false”

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, "");//读取"dalvik.vm.execution-mode"属性值,“int:portable” : “int:fast”: “int:jit”

if (strcmp(propBuf, "int:portable") == 0) {

executionMode = kEMIntPortable;

} else if (strcmp(propBuf, "int:fast") == 0) {

executionMode = kEMIntFast;

#if defined(WITH_JIT)

} else if (strcmp(propBuf, "int:jit") == 0) {

executionMode = kEMJitCompiler;

#endif

}

property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");//读取"dalvik.vm.stack-trace-file"属性值

property_get("dalvik.vm.check-dex-sum", propBuf, "");//读取"dalvik.vm.check-dex-sum"属性值,“true” : “false”

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, "");//读取"dalvik.vm.enableassertions"属性值

strcpy(jniOptsBuf, "-Xjniopts:");

property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");//读取"dalvik.vm.jniopts"属性值

/* 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);

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";

strcpy(heapsizeOptsBuf, "-Xmx");

property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");//读取"dalvik.vm.heapsize"属性值

//LOGI("Heap size: %s", heapsizeOptsBuf);

opt.optionString = heapsizeOptsBuf;

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, "");//读取"dalvik.vm.dexopt-flags"属性值

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;

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 */

#ifdef HAVE_ANDROID_OS

/* use android ADB transport */

opt.optionString ="-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";

#else

/* use TCP socket; address=0 means start at port 8000 and probe up */

LOGI("Using TCP socket for JDWP\n");

opt.optionString ="-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";

#endif

mOptions.add(opt);

char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];

property_get("dalvik.vm.deadlock-predict", propBuf, "");

if (strlen(propBuf) > 0) {

strcpy(enableDPBuf, "-Xdeadlockpredict:");

strcat(enableDPBuf, propBuf);

opt.optionString = enableDPBuf;

mOptions.add(opt);

}

LOGD("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);

}

#if defined(WITH_JIT)

/* 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);

}

#endif

if (executionMode == kEMIntPortable) {

opt.optionString = "-Xint:portable";

mOptions.add(opt);

} else if (executionMode == kEMIntFast) {

opt.optionString = "-Xint:fast";

mOptions.add(opt);

#if defined(WITH_JIT)

} else if (executionMode == kEMJitCompiler) {

opt.optionString = "-Xint:jit";

mOptions.add(opt);

#endif

}

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';

LOGI("Assertions enabled: '%s'\n", enableAssertBuf);

opt.optionString = enableAssertBuf;

mOptions.add(opt);

} else {

LOGV("Assertions disabled\n");

}

if (jniOptsBuf[10] != '\0') {

LOGI("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函数创建虚拟机,关于虚拟机创建过程可参考dalvik\vm\Jni.c

*/

if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {

LOGE("JNI_CreateJavaVM failed\n");

goto bail;

}

result = 0;

bail:

free(stackTraceFile);

return result;

}

5.AndroidRuntime.cpp 注册JNI函数

第4步中已经创建好了虚拟机,因此需要给该虚拟机注册一些JNI函数。

[java] view
plaincopy

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.) 设置线程创建函数为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函数,所有的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;

}

[java] view
plaincopy

//JNI函数注册方法

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)

{

for (size_t i = 0; i < count; i++) {

if (array[i].mProc(env) < 0) {

#ifndef NDEBUG

LOGD("----------!!! %s failed to load\n", array[i].mName);

#endif

return -1;

}

}

return 0;

}

[html] view
plaincopy

//gRegJNI全局数组中

static const RegJNIRec gRegJNI[] = {

REG_JNI(register_android_debug_JNITest),

REG_JNI(register_com_android_internal_os_RuntimeInit),

REG_JNI(register_android_os_SystemClock),

REG_JNI(register_android_util_EventLog),

REG_JNI(register_android_util_Log),

REG_JNI(register_android_util_FloatMath),

REG_JNI(register_android_text_format_Time),

REG_JNI(register_android_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),

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_hardware_fm_fmradio),

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),

};

6.ZygoteInit.java 调用了com.android.internal.os.ZygoteInit类的main函数

[java] view
plaincopy

public static void main(String argv[]) {

//传入的参数argv = ["com.android.internal.os.ZygoteInit","true"]

try {

//设置虚拟机的最小堆栈大小

VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);

// Start profiling the zygote initialization.启动性能统计

SamplingProfilerIntegration.start();

//注册zygote等待客户端连接的socket

registerZygoteSocket();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());

//预加载java类和资源

preloadClasses();

preloadResources();

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,执行垃圾回收

gc();

// If requested, start system server directly from Zygote

if (argv.length != 2) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

if (argv[1].equals("true")) {

//启动SystemServer进程

startSystemServer();

} else if (!argv[1].equals("false")) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

Log.i(TAG, "Accepting command socket connections");

//boolean ZYGOTE_FORK_MODE = false; 因此调用runSelectLoopMode()函数

if (ZYGOTE_FORK_MODE) {

runForkMode();

} else {

runSelectLoopMode();

}

closeServerSocket(); //关闭socket

} catch (MethodAndArgsCaller caller) {

//捕获SytemServer进程调用RuntimeInit.java 中zygoteInit函数抛出的MethodAndArgsCaller异常

caller.run();

} catch (RuntimeException ex) {

Log.e(TAG, "Zygote died with exception", ex);

closeServerSocket();

throw ex;

}

}

该main函数的作用:

<1>.调用registerZygoteSocket函数创建了一个socket接口,建立IPC通信的服务端;

<2> preloadClasses,preloadResources函数预加载类和资源

<2>.调用startSystemServer函数来启动SystemServer组件;

<3>.调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。

7.ZygoteInit.java 建立socket通信服务端

zygote 并没有采用binder通信机制,而是采用基于AF_UNIX类型的socket通信方式

[java] view
plaincopy

private static void registerZygoteSocket() {

if (sServerSocket == null) {

int fileDesc;

try {

//从环境变量中获取文件句柄,这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,关于socket的创建及环境变量的设置请参考init进程源码分析

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将监听并接受客户端请求

sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));

} catch (IOException ex) {

throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);

}

}

}

8.ZygoteInit.java 预加载类和资源

[java] view
plaincopy

private static void preloadClasses() {

final VMRuntime runtime = VMRuntime.getRuntime();

//通过反射机制获取输入流,类资源文件为"preloaded-clprr"

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.

//设置有效组ID和有效用户ID

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反射机制加载类,每一行储存的是类名

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 执行时间比较长,也是导致android系统启动慢的原因。

加载共享资源

[java] view
plaincopy

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();

}

}

9.ZygoteInit.java 启动SystemServer

[java] view
plaincopy

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",

"com.android.server.SystemServer",

};

ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {

parsedArgs = new ZygoteConnection.Arguments(args); //把字符串数组中的参数转换为Arguments对象

/*

* 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;

/* fork一个子进程作为SystemServer进程*/

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) {

//SystemServer进程的初始化设置

handleSystemServerProcess(parsedArgs);

}

return true;

}

Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。

10.ZygoteInit.java 循环等待客户端的连接

[java] view
plaincopy

private static void runSelectLoopMode() throws MethodAndArgsCaller {

ArrayList<FileDescriptor> fds = new ArrayList(); //存储所有客户端连接的socket文件句柄

ArrayList<ZygoteConnection> peers = new ArrayList();//存储所有客户端连接

FileDescriptor[] fdArray = new FileDescriptor[4];

fds.add(sServerSocket.getFileDescriptor());//保存先前创建用于等待客户端连接的服务端socket

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) {

//有一个客户端连接

ZygoteConnection newPeer = acceptCommandPeer();

peers.add(newPeer);

fds.add(newPeer.getFileDesciptor());

} else {

boolean done;

//客户端发送了请求,peers.get(index)获取当前客户端的ZygoteConnection,并调用当前连接的runOnce()函数创建新的应用程序

done = peers.get(index).runOnce();

if (done) {

peers.remove(index);

fds.remove(index);

}

}

}

}

zygote总结:

1.创建AppRuntime对象,并调用它的start函数;

2.调用startVm创建Java虚拟机;

3.调用startReg函数来注册JNI函数;

4.调用ZygoteInit类的main函数,从此就进入了Java世界;

5.调用registerZygoteSocket 注册一个服务端socket;

6.调用preloadClasses 函数加载类资源;

7.调用preloadResources函数加载系统资源;

8.调用startSystemServer函数创建SystemServer进程;

9.调用runSelectLoopMode函数进入服务端socket监听;

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: