Android开机流程分析 -- Zygote

一、第一个Dalvik虚拟机Zygote

    为什么将Zygote叫做受精卵呢?是因为在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的。

    Android应用程序是由java语言编写的,运行于各自独立的Dalvik虚拟机中。那么Android的处理机制是什么呢?Android首先创建一个Zygote虚拟机,然后通过它孵化出其他的虚拟机进程,进而共享虚拟机内存和框架层资源,这样大幅度提高了应用程序启动和运行速度。

1、Zygote配置

   zygote是在init.rc中定义的守护进程服务(Daemon Service),在Android5.0中,Zygote的启动发生了一些变化,以前直接放在init.rc中的代码块放到了单独的文件中,在init.rc中通过import的方式引入文件,如下:

import /init.${ro.zygote}.rc

   从上面的语句可以看出,init.rc并不是直接引入某个固定的文件,而是根据属性“ro.zygote”的内容来引入不同的文件。这是因为Android从5.0开始,Android开始支持64位的编译,Zygote本身也会有32位和64位版本的区别,因此,这里通过ro.zygote属性来控制启动不同版本的Zygote进程。该文件位于system/core/init/下,目录下有Init.zygote64.rc,Init.zygote32.rc,Init.zygote32_64.rc,Init.zygot64_32.rc,至于调用哪个是由硬件决定的,这里以Init.zygote64_32.rc为例,代码如下:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
       class main             #class是一个Option,指定zygote服务的类型是main
    socket zygote stream 660 root system         #socket是一个Option,创建一个Socket名为dev/socket/zygote,Socket类型是stream,权限为660
    onrestart write /sys/android_power/request_state wake   #onrestart是一个Option,设置zygote重启时需要执行的Command
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin--zygote --socket-name=zygote_secondary
    class main
    socket zygote_secondary stream 660 root system
    onrestart restart zygote

   从代码中我们可以看出,系统定义了两个Zygote服务:zygote和zygote_secondary。这两个服务最大的区别是启动的可执行文件不同,一个是app_process64,另一个是app_process32。由关键字service告诉init进程创建一个名为“zygote”的进程,这个zygote进程要执行的程序是/system/bin/app_process64(可执行文件),给这个zygote进程传递了5个参数,分别是-Xzygote,/system/bin,--zygote,--start-system-server,--socket-name=zygote;另外zygote服务需要开启一个Socket,并且zygote重启时,需要执行下面的命令:

    修改/sys/android_power/request_state;修改/sys/power/state;重启media;重启netd。

2、zygote的执行

我们先看下Zygote进程的初始化过程,如下:



从上面的分析中可以看出zygote要执行的程序是/system/bin/app_process,它的源码位于frameworks/base/cmds/app_process/App_main.cpp文件中,入口函数是main。

main函数的主要功能是解析启动参数。    

在源码中提供了app_process的启动方式,参数如下:

        app_process [java-options(虚拟机参数)] cmd-dir(运行目录) start-calss-name(java类) [options(参数)]

[java-options]:指定启动dalvik虚拟机时传递给虚拟机的参数,以“-”开头;

cmd-dir:要运行的进程所在的目录,通常是/system/bin;

start-class-name:指定要加载到虚拟机的类,而后调用其main方法;使用参数“--zygote”时会直接执行ZygoteInit类。

[options]:指定传递给类的参数;以符号“--”开头。参数“--zygote”表示要启动zygote进程。参数“--application”表示要以普通进程的方式执行java代码。

    我们看下App_main中main函数的代码,AppRuntime是在app_process中定义的类,继承了系统的AndroidRuntime类。AndroidRuntime类的主要作用是创建和初始化虚拟机。

int main(int argc, char* const argv[])
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
        // EINVAL. Don't die on such kernels.
        if (errno != EINVAL) {
            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
            return 12;
        }
    }

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;   /* 因为argv[0]不是参数,所以忽略argv[0],并将argc减1*/

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.

    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { /* 如果参数中指定了--zygote,则启动zygote,niceName设置为“zygote” */
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;   /* 是否启动System Server */
        } else if (strcmp(arg, "--application") == 0) {
            application = true; /* 是否启动application */
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);   /* 是否指定了nice name */
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));//非zygote模式
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());/* 根据nicename调用系统函数prctl,open,write修改进程名,由于启动过程中指定了--zygote参数,所以这里的进程名是zygote */
    }
      /* if-else用于匹配两种启动类型,启动zygote或者是启动application */
    if (zygote) {   /* 如果参数中指定了--zygote,则启动zygote */
        runtime.start("com.android.internal.os.ZygoteInit", args);
    } else if (className) {   /* 启动应用程序 */
        runtime.start("com.android.internal.os.RuntimeInit", args);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

    从App_main的main函数中可以看出调用AppRuntime的start方法启动ZygoteInit。

二、ZygoteInit启动过程

    AppRuntime的实现代码位于frameworks\base\cmds\app_process\App_main.cpp中,它是AndroidRuntime的派生类,其start方法便是继承自AndroidRuntime。

    AndroidRuntime负责开启Android运行时环境,代码位于framewroks\base\core\jni\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.
 */ 
/* 根据上面的分析,init.rc中指定了参数--zygote,那么传入到这个函数的参数分别是:classname=“com.android.internal.os.ZygoteInit;options=start-system-server” */
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == 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)));
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);  /* 设置环境变量 */
    }

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* start the virtual machine 开启虚拟机*/
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (<span style="color:#3333ff;">startVm</span>(&mJavaVM, &env) != 0) {
        return;
    }
    /* 开启虚拟机后执行的工作,这里是空函数体,什么都没做。运行时实际调用的是AppRuntime的onVmCreated函数,保存了类的全局引用。*/
    onVmCreated(env);

    /*
     * Register android functions.注册Android JNI函数
     */
    if (<span style="color:#3333ff;">startReg</span>(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.调用指定类的main函数,并传入参数classname和options。在这之前需要将参数classname和options通过JNI函数转化为JAVA可识别的参数类型。
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;   /* 用于转换classname为java可识别类型的字符串 */

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);/* 调用JNI函数生成一个对象数组,数组大小为options.size()+1(这里为2,只有一个参数start-system-server),存放字符串类型的元素 */
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr); /* 将转化后的classname存入数组 */

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);/* 将转化后的options存入数组 */
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
        /* 将classname转化为slash格式的字符串,以符合JNI的命名规则。这里将com.android.internal.os.ZygoteInit转化为com/android/internal/os/ZygoteInit,用于通过JNI函数findClass找到这个JAVA类。 */
    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的main方法的方法ID */
        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 {
            /* 通过调用JNI函数CallStaticVoidMethod调用JAVA类ZygoteInit的main方法,并传入参数com.android.internal.os.ZygoteInit和参数true */
            env-><span style="color:#3333ff;">CallStaticVoidMethod</span>(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);/* 将转化后的classname存入数组 */
   
        /* detach当前线程,释放JNI资源并关闭虚拟机 */
    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

   AndroidRuntime的start方法开启了Android运行时,start方法主要做了三部分工作:

  • 创建Dalvik虚拟机:startVm;
  • 注册JNI方法:startReg;
  • 开启java世界:JNIEnv.CallStaticVoidMethod。

1、创建Dalvik虚拟机

    首先分析start工作的第一步,Dalvik虚拟机是调用startVM函数创建的,该函数位于AndroidRuntime.cpp中。代码如下:

/*
 * Start the Dalvik Virtual Machine.
 *
 * Various arguments, most determined by system properties, are passed in.
 * The "mOptions" vector is updated.
 *
 * CAUTION: when adding options in here, be careful not to put the
 * char buffer inside a nested scope.  Adding the buffer to the
 * options using mOptions.add() does not copy the buffer, so if the
 * buffer goes out of scope the option may be overwritten.  It's best
 * to put the buffer at the top of the function so that it is more
 * unlikely that someone will surround it in a scope at a later time
 * and thus introduce a bug.
 *
 * Returns 0 on success.
 */
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
    int result = -1;
    JavaVMInitArgs initArgs;
    char propBuf[PROPERTY_VALUE_MAX];/* 虚拟机的配置参数 */
    char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + 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 gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
    char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
    char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
    char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
    char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
    char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
    char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
    char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
    char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
    char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
    char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
    char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
    char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
    char extraOptsBuf[PROPERTY_VALUE_MAX];
    char voldDecryptBuf[PROPERTY_VALUE_MAX];
    enum {
      kEMDefault,
      kEMIntPortable,
      kEMIntFast,
      kEMJitCompiler,
    } executionMode = kEMDefault;
    char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX];
    char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX];
    char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX];
    char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX];
    char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX];
    char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 +
                                    PROPERTY_VALUE_MAX];
    char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX];
    char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + PROPERTY_VALUE_MAX];
    char langOption[sizeof("-Duser.language=") + 3];
    char regionOption[sizeof("-Duser.region=") + 3];
    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
    char jitOpBuf[sizeof("-Xjitop:")-1 + PROPERTY_VALUE_MAX];
    char jitMethodBuf[sizeof("-Xjitmethod:")-1 + PROPERTY_VALUE_MAX];
    char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];

    /* 通过属性系统获得dalvik.vm.checkjni的配置参数,checkjni是开发阶段一个非常重要的属性
     * 通过它可以对JNI调用参数进行自动检查,还可以定位一些JNI产生的异常,比如JNI内存泄露。
     * 如果checkjni设置为true,JNI调用过程就可以由dalvikvm记录并显示在logcat上。
     * JNI检查会大幅度降低性能,只能在eng或userDebug版本上进行配置。 */
    bool checkJni = false;
    property_get("dalvik.vm.checkjni", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
        checkJni = true;
    } else if (strcmp(propBuf, "false") != 0) {
        /* property is neither true nor false; fall back on kernel parameter */
        property_get("ro.kernel.android.checkjni", propBuf, "");
        if (propBuf[0] == '1') {
            checkJni = true;
        }
    }
    ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
    if (checkJni) {
        /* extended JNI checking 选项“-Xcheck:jni”,用来启动JNI方法检查。*/
        addOption("-Xcheck:jni");

        /* set a cap on JNI global references,设定JNI全局引用的个数不能超过2000 */
        addOption("-Xjnigreflimit:2000");

        /* with -Xcheck:jni, this provides a JNI function call trace */
        //addOption("-verbose:jni");
    }

    /* 指定虚拟机的执行模式,Dalvik虚拟机支持三种运行模式,分别为Portable、Fast、Jit */
    property_get("dalvik.vm.execution-mode", propBuf, "");
    if (strcmp(propBuf, "int:portable") == 0) {
        executionMode = kEMIntPortable;/* Dalvik虚拟机以可移植的方式进行编译,即编译出来的虚拟机可以在任何平台上运行 */
    } else if (strcmp(propBuf, "int:fast") == 0) {
        executionMode = kEMIntFast;/* Fast是针对当前平台对Dalvik虚拟机进行编译,这样编译出来的Dalvik虚拟机可以进行特殊的优化,从而使得它能更快的运行程序 */
    } else if (strcmp(propBuf, "int:jit") == 0) {
        executionMode = kEMJitCompiler;/* Jit不是解释执行代码,二是将代码动态编译成本地语言后再执行 */
    }

    /* -Xstacktracefile:用来指定调用堆栈输出文件。
     * 当虚拟机收到SIGQUIT(Ctrl-\或者kill -3)信号时,会将所有线程的堆栈信息写入指定文件。
     * 可以通过dalvik.vm.stack-trace-file系统属性来指定调用堆栈输出文件。
     * 这样可以保留异常发生时的现场,方便调试定位出错原因。*/
    parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");

    /* 对优化过的DEX文件进行检测的配置参数,关闭后会提升性能,但如果文件损坏会导致虚拟机崩溃。 */
    property_get("dalvik.vm.check-dex-sum", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
        /* perform additional DEX checksum tests */
        addOption("-Xcheckdexsum");
    }

    property_get("log.redirect-stdio", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
        /* convert stdout/stderr to log messages */
        addOption("-Xlog-stdio");
    }

    /* 设置是否支持java的断言表达式 */
    strcpy(enableAssertBuf, "-ea:");
    property_get("dalvik.vm.enableassertions", enableAssertBuf+sizeof("-ea:")-1, "");
    if (enableAssertBuf[sizeof("-ea:")-1] != '\0') {
        /* accept "all" to mean "all classes and packages" */
        if (strcmp(enableAssertBuf+sizeof("-ea:")-1, "all") == 0)
            enableAssertBuf[3] = '\0'; // truncate to "-ea"
        ALOGI("Assertions enabled: '%s'\n", enableAssertBuf);
        addOption(enableAssertBuf);
    } else {
        ALOGV("Assertions disabled\n");
    }

    strcpy(jniOptsBuf, "-Xjniopts:");
    if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {
        ALOGI("JNI options: '%s'\n", jniOptsBuf);
    }

    /* route exit() to our handler */
    addOption("exit", (void*) runtime_exit);

    /* route fprintf() to our handler */
    addOption("vfprintf", (void*) runtime_vfprintf);

    /* register the framework-specific "is sensitive thread" hook */
    addOption("sensitiveThread", (void*) runtime_isSensitiveThread);

    /* enable verbose; standard options are { jni, gc, class } */
    //addOption("-verbose:jni");
    addOption("-verbose:gc");
    //addOption("-verbose:class");

    /*
     * The default starting and maximum size of the heap.  Larger
     * values should be specified in a product property override.
     * 设置虚拟机heap的大小,包括启动值(heapstartsize)和最大值(heapsize)*/
    parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
    parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");

    // Increase the main thread's interpreter stack size for bug 6315322.
    addOption("-XX:mainThreadStackSize=24K");

    // Set the max jit code cache size.  Note: size of 0 will disable the JIT.
    parseRuntimeOption("dalvik.vm.jit.codecachesize",
                       jitcodecachesizeOptsBuf,
                       "-Xjitcodecachesize:");

    parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
    parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
    parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
    parseRuntimeOption("dalvik.vm.heaptargetutilization",
                       heaptargetutilizationOptsBuf,
                       "-XX:HeapTargetUtilization=");

    property_get("ro.config.low_ram", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
      addOption("-XX:LowMemoryMode");
    }

    parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
    parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");

    /*
     * Enable 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) {
                addOption(val);
            }
        }

        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) {
                addOption(val);
            }
        }

        opc = strstr(dexoptFlagsBuf, "m=y");    /* register map */
        if (opc != NULL) {
            addOption("-Xgenregmap");

            /* turn on precise GC while we're at it */
            addOption("-Xgc:precise");
        }
    }

    /* enable debugging; set suspend=y to pause during VM init */
    /* use android ADB transport */
    addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y");

    parseRuntimeOption("dalvik.vm.lockprof.threshold",
                       lockProfThresholdBuf,
                       "-Xlockprofthreshold:");

    /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
    parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:");

    /* Force interpreter-only mode for selected methods */
    parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:");

    if (executionMode == kEMIntPortable) {
        addOption("-Xint:portable");
    } else if (executionMode == kEMIntFast) {
        addOption("-Xint:fast");
    } else if (executionMode == kEMJitCompiler) {
        addOption("-Xint:jit");
    }

    // libart tolerates libdvm flags, but not vice versa, so only pass some options if libart.
    property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so");
    bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);

    if (libart) {
        // If we booting without the real /data, don't spend time compiling.
        property_get("vold.decrypt", voldDecryptBuf, "");
        bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
                                 (strcmp(voldDecryptBuf, "1") == 0));

        // Extra options for boot.art/boot.oat image generation.
        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
                                   "-Xms", "-Ximage-compiler-option");
        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
                                   "-Xmx", "-Ximage-compiler-option");
        if (skip_compilation) {
            addOption("-Ximage-compiler-option");
            addOption("--compiler-filter=verify-none");
        } else {
            parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
                                "--compiler-filter=", "-Ximage-compiler-option");
        }

        // Make sure there is a preloaded-classes file.
        if (!hasFile("/system/etc/preloaded-classes")) {
            ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
                  strerror(errno));
            goto bail;
        }
        addOption("-Ximage-compiler-option");
        addOption("--image-classes=/system/etc/preloaded-classes");

        // If there is a compiled-classes file, push it.
        if (hasFile("/system/etc/compiled-classes")) {
            addOption("-Ximage-compiler-option");
            addOption("--compiled-classes=/system/etc/compiled-classes");
        }

        property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
        parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");

        // Extra options for DexClassLoader.
        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
                                   "-Xms", "-Xcompiler-option");
        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
                                   "-Xmx", "-Xcompiler-option");
        if (skip_compilation) {
            addOption("-Xcompiler-option");
            addOption("--compiler-filter=verify-none");
        } else {
            parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
                                "--compiler-filter=", "-Xcompiler-option");
        }
        property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
        parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");

    }

    /* extra options; parse this late so it overrides others */
    property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
    parseExtraOpts(extraOptsBuf, NULL);

    /* Set the properties for locale */
    {
        strcpy(langOption, "-Duser.language=");
        strcpy(regionOption, "-Duser.region=");
        readLocale(langOption, regionOption);
        addOption(langOption);
        addOption(regionOption);
    }

    /*
     * Set profiler options
     */
    if (libart) {
        // Whether or not the profiler should be enabled.
        property_get("dalvik.vm.profiler", propBuf, "0");
        if (propBuf[0] == '1') {
            addOption("-Xenable-profiler");
        }

        // Whether the profile should start upon app startup or be delayed by some random offset
        // (in seconds) that is bound between 0 and a fixed value.
        property_get("dalvik.vm.profile.start-immed", propBuf, "0");
        if (propBuf[0] == '1') {
            addOption("-Xprofile-start-immediately");
        }

        // Number of seconds during profile runs.
        parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:");

        // Length of each profile run (seconds).
        parseRuntimeOption("dalvik.vm.profile.duration-secs",
                           profileDuration,
                           "-Xprofile-duration:");

        // Polling interval during profile run (microseconds).
        parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:");

        // Coefficient for period backoff.  The the period is multiplied
        // by this value after each profile run.
        parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:");

        // Top K% of samples that are considered relevant when
        // deciding if the app should be recompiled.
        parseRuntimeOption("dalvik.vm.profile.top-k-thr",
                           profileTopKThreshold,
                           "-Xprofile-top-k-threshold:");

        // The threshold after which a change in the structure of the
        // top K% profiled samples becomes significant and triggers
        // recompilation. A change in profile is considered
        // significant if X% (top-k-change-threshold) of the top K%
        // (top-k-threshold property) samples has changed.
        parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr",
                           profileTopKChangeThreshold,
                           "-Xprofile-top-k-change-threshold:");

        // Type of profile data.
        parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:");

        // Depth of bounded stack data
        parseRuntimeOption("dalvik.vm.profile.stack-depth",
                           profileMaxStackDepth,
                           "-Xprofile-max-stack-depth:");

        // Native bridge library. "0" means that native bridge is disabled.
        property_get("ro.dalvik.vm.native.bridge", propBuf, "");
        if (propBuf[0] == '\0') {
            ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
        } else if (strcmp(propBuf, "0") != 0) {
            snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
                     "-XX:NativeBridge=%s", propBuf);
            addOption(nativeBridgeLibrary);
        }
    }

    initArgs.version = JNI_VERSION_1_4;
    initArgs.options = mOptions.editArray();
    initArgs.nOptions = mOptions.size();
    initArgs.ignoreUnrecognized = JNI_FALSE;

    /*
     * Initialize the VM.创建java虚拟机对象。
     * 执行成功后,虚拟机便准备就绪,这时候java世界就可以分发JNI调用了。
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        goto bail;
    }

    result = 0;

bail:
    return result;
}
    根据代码可以看出startVM主要做了两部分工作:一是通过属性系统获取大量虚拟机配置信息,以此设置虚拟机参数;二是调用JNI_CreateJavaVM函数创建虚拟机实例。

    虚拟机参数很多,可以通过adb命令查看:adb shell dalvikvm。

    JNI_CreateJavaVM不再向下跟踪,可以参考:点击打开链接

2、注册JNI方法

    上面我们分析了是如何创建Dalvik虚拟机的,下面我们接着分析start方法的第二步重要工作:注册Android核心类的JNI函数。这些函数是java世界调用native方法的基础,是连接java世界和C/C++世界的桥梁。 

<span style="font-size:12px;">/*
 * 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.)
     */
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

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

    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    //createJavaThread("fubar", quickTest, (void*) "hello");

    return 0;
}</span>

 

在startReg函数中首先调用了androidSetCerateThreadFunc函数,这个函数用来设置一个线程创建钩子javaCreateThreadEtc。这个线程创建钩子是用来干什么的呢?是用来初始化一个Native线程的JNI环境的,也就是说当我们在C++代码中创建一个Native线程的时候,会调用javaCreateThreadEtc函数来初始化该Native线程的JNI环境。

    调用register_jni_procs函数来注册Android核心类的JNI方法。在注册JNI方法的过程中,需要在Native代码中引用到一些JAVA对象,这些Java对象引用需要记录在当前线程的一个Native堆栈中。但是此时Dalvik虚拟机还没有真正运行起来,也就是当前线程的Native堆栈还没有准备就绪。那么在这种情况下,Android是如何处理的呢?在注册JNI方法之前,调用JNIEnv对象的PushLocalFrame函数在当前线程的Native堆栈中压入一个帧(Frame),这个帧是一个本地帧,只是用来保存java对象在Native代码中的本地引用;并且在注册JNI方法之后,调用JNIEnv对象的PopLocalFrame函数将帧弹出堆栈。在本地函数的入口处调用PushLocalFrame,在函数返回前调用PopLocalFrame,这样在两个函数之间创建的局部引用都会有效管理和释放,也就高效管理了局部引用的生命周期。

    startReg函数的关键是调用register_jni_procs函数注册JNI方法。

注意:在Android应用框架层有很多地方调用Native方法,这些方法的实现都借助于本地方法。这里便是注册Native方法的JNI实现方法,Android是采用注册方式实现Native方法和JNI方法的关联。register_jni_procs的实现如下:

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
            return -1;
        }
    }
    return 0;
}
   从前面的调用过程可以知道 ,参数array指向的是全局变量gRegJNI所描述的一个JNI方法注册函数表,其中,每一个表项都用一个RegJNIRec对象来描述,而每一个RegJNIRec对象都有一个成员变量mProc,指向一个JNI方法注册函数。通过依次调用这些注册函数,就可以将Android核心类的JNI方法注册到前面的所创建的Dalvik虚拟机中去。

    那么我们看一下RegJNIRec到底是什么呢,代码如下:

#ifdef NDEBUG
    #define REG_JNI(name)      { name } /* 定义REG_JNI宏,宏以name为参数*/
    struct RegJNIRec { /* 定义一个结构体RegJNIRec,结构体的元素是一个函数指针,参数类型是(JNIEnv*) */
        int (*mProc)(JNIEnv*);
    };
#else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
#endif
    从代码中可以看出RegJNIRec是一个结构体,结构体的元素是一个函数指针。我们看一下gRegJNI描述的JNI方法注册函数表都注册了哪些Android核心类的JNI方法,代码如下:

static const RegJNIRec gRegJNI[] = {
    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_content_AssetManager),
    REG_JNI(register_android_content_StringBlock),
    REG_JNI(register_android_content_XmlBlock),
    REG_JNI(register_android_emoji_EmojiFactory),
    REG_JNI(register_android_text_AndroidCharacter),
    REG_JNI(register_android_text_StaticLayout),
    REG_JNI(register_android_text_AndroidBidi),
    REG_JNI(register_android_view_InputDevice),
    REG_JNI(register_android_view_KeyCharacterMap),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_os_Parcel),
    REG_JNI(register_android_nio_utils),
    REG_JNI(register_android_graphics_Graphics),
    REG_JNI(register_android_view_DisplayEventReceiver),
    REG_JNI(register_android_view_RenderNode),
    REG_JNI(register_android_view_RenderNodeAnimator),
    REG_JNI(register_android_view_GraphicBuffer),
    REG_JNI(register_android_view_GLES20Canvas),
    REG_JNI(register_android_view_HardwareLayer),
    REG_JNI(register_android_view_ThreadedRenderer),
    REG_JNI(register_android_view_Surface),
    REG_JNI(register_android_view_SurfaceControl),
    REG_JNI(register_android_view_SurfaceSession),
    REG_JNI(register_android_view_TextureView),
    REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper),
    REG_JNI(register_com_google_android_gles_jni_EGLImpl),
    REG_JNI(register_com_google_android_gles_jni_GLImpl),
    REG_JNI(register_android_opengl_jni_EGL14),
    REG_JNI(register_android_opengl_jni_EGLExt),
    REG_JNI(register_android_opengl_jni_GLES10),
    REG_JNI(register_android_opengl_jni_GLES10Ext),
    REG_JNI(register_android_opengl_jni_GLES11),
    REG_JNI(register_android_opengl_jni_GLES11Ext),
    REG_JNI(register_android_opengl_jni_GLES20),
    REG_JNI(register_android_opengl_jni_GLES30),
    REG_JNI(register_android_opengl_jni_GLES31),
    REG_JNI(register_android_opengl_jni_GLES31Ext),

    REG_JNI(register_android_graphics_Bitmap),
    REG_JNI(register_android_graphics_BitmapFactory),
    REG_JNI(register_android_graphics_BitmapRegionDecoder),
    REG_JNI(register_android_graphics_Camera),
    REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
    REG_JNI(register_android_graphics_Canvas),
    REG_JNI(register_android_graphics_CanvasProperty),
    REG_JNI(register_android_graphics_ColorFilter),
    REG_JNI(register_android_graphics_DrawFilter),
    REG_JNI(register_android_graphics_FontFamily),
    REG_JNI(register_android_graphics_Interpolator),
    REG_JNI(register_android_graphics_LayerRasterizer),
    REG_JNI(register_android_graphics_MaskFilter),
    REG_JNI(register_android_graphics_Matrix),
    REG_JNI(register_android_graphics_Movie),
    REG_JNI(register_android_graphics_NinePatch),
    REG_JNI(register_android_graphics_Paint),
    REG_JNI(register_android_graphics_Path),
    REG_JNI(register_android_graphics_PathMeasure),
    REG_JNI(register_android_graphics_PathEffect),
    REG_JNI(register_android_graphics_Picture),
    REG_JNI(register_android_graphics_PorterDuff),
    REG_JNI(register_android_graphics_Rasterizer),
    REG_JNI(register_android_graphics_Region),
    REG_JNI(register_android_graphics_Shader),
    REG_JNI(register_android_graphics_SurfaceTexture),
    REG_JNI(register_android_graphics_Typeface),
    REG_JNI(register_android_graphics_Xfermode),
    REG_JNI(register_android_graphics_YuvImage),
    REG_JNI(register_android_graphics_pdf_PdfDocument),
    REG_JNI(register_android_graphics_pdf_PdfEditor),
    REG_JNI(register_android_graphics_pdf_PdfRenderer),

    REG_JNI(register_android_database_CursorWindow),
    REG_JNI(register_android_database_SQLiteConnection),
    REG_JNI(register_android_database_SQLiteGlobal),
    REG_JNI(register_android_database_SQLiteDebug),
    REG_JNI(register_android_os_Debug),
    REG_JNI(register_android_os_FileObserver),
    REG_JNI(register_android_os_MessageQueue),
    REG_JNI(register_android_os_SELinux),
    REG_JNI(register_android_os_Trace),
    REG_JNI(register_android_os_UEventObserver),
    REG_JNI(register_android_net_LocalSocketImpl),
    REG_JNI(register_android_net_NetworkUtils),
    REG_JNI(register_android_net_TrafficStats),
    REG_JNI(register_android_os_MemoryFile),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_com_android_internal_os_Zygote),
    REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
    REG_JNI(register_android_hardware_Camera),
    REG_JNI(register_android_hardware_camera2_CameraMetadata),
    REG_JNI(register_android_hardware_camera2_legacy_LegacyCameraDevice),
    REG_JNI(register_android_hardware_camera2_legacy_PerfMeasurement),
    REG_JNI(register_android_hardware_camera2_DngCreator),
    REG_JNI(register_android_hardware_SensorManager),
    REG_JNI(register_android_hardware_SerialPort),
    REG_JNI(register_android_hardware_SoundTrigger),
    REG_JNI(register_android_hardware_UsbDevice),
    REG_JNI(register_android_hardware_UsbDeviceConnection),
    REG_JNI(register_android_hardware_UsbRequest),
    REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
    REG_JNI(register_android_media_AudioRecord),
    REG_JNI(register_android_media_AudioSystem),
    REG_JNI(register_android_media_AudioTrack),
    REG_JNI(register_android_media_JetPlayer),
    REG_JNI(register_android_media_RemoteDisplay),
    REG_JNI(register_android_media_ToneGenerator),

    REG_JNI(register_android_opengl_classes),
    REG_JNI(register_android_server_NetworkManagementSocketTagger),
    REG_JNI(register_android_ddm_DdmHandleNativeHeap),
    REG_JNI(register_android_backup_BackupDataInput),
    REG_JNI(register_android_backup_BackupDataOutput),
    REG_JNI(register_android_backup_FileBackupHelperBase),
    REG_JNI(register_android_backup_BackupHelperDispatcher),
    REG_JNI(register_android_app_backup_FullBackup),
    REG_JNI(register_android_app_ActivityThread),
    REG_JNI(register_android_app_NativeActivity),
    REG_JNI(register_android_view_InputChannel),
    REG_JNI(register_android_view_InputEventReceiver),
    REG_JNI(register_android_view_InputEventSender),
    REG_JNI(register_android_view_InputQueue),
    REG_JNI(register_android_view_KeyEvent),
    REG_JNI(register_android_view_MotionEvent),
    REG_JNI(register_android_view_PointerIcon),
    REG_JNI(register_android_view_VelocityTracker),

    REG_JNI(register_android_content_res_ObbScanner),
    REG_JNI(register_android_content_res_Configuration),

    REG_JNI(register_android_animation_PropertyValuesHolder),
    REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
    REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
};

    这里使用了宏REG_JNI,将函数名传递给结构体RegJNIRec的mProc函数指针。这些函数最终调用了jniRegisterNativeMethods方法注册JNI方法。

    至此,JNI方法注册就分析到这里。

3、开启java世界

    在AndroidRuntime的start方法中是通过CallStaticVoidMethod这个JNI函数调用ZygoteInit文件的main函数来开启java世界的。ZygoteInit文件位于frameworks/base/core/java/com/android/internal/os/ZygoteInit.java,定位到main方法,代码如下:

    public static void main(String argv[]) {
        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            registerZygoteSocket(socketName);/* 注册zygote服务所需的Socket,用来接收请求 */
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload();/* 加载class资源和resource资源 */
            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();/* 强制gc */

            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false);

            if (startSystemServer) {
                startSystemServer(abiList, socketName);/* 启动system_server */
            }

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

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();/* zygote异常退出 */
            throw ex;
        }
    }
ZygoteInit的main方法主要做了5部分工作:
  • 注册zygote的Socket;
  • 预加载Class资源和Resource资源;
  • 启动system_server;
  • 执行runSelectLoop方法;
  • 执行MethodAndArgsCaller的run方法,该方法将执行SystemServer的main函数。
    这5部分的工作是Android应用程序启动和运行的基础。通过zygote的Socket,ActivityManagerService便可以通过zygote启动新的应用进程;通过预加载资源,让不同应用程序共享框架层资源,提高运行效率;启动system_server,将开启Android的Native system service和Java System Service,这是应用框架层运行的基础;通过runSelectLoop,便可以处理新的应用程序运行请求。

三、Zygote开启java世界

1、注册Zygote的Socket

    注册zygote服务所需要的Socket,是通过registerZygoteSocket函数来实现的,该函数绑定了zygote中的Socket,用于接收ActivityManagerService中启动应用程序的请求。

    /**
     * Registers a server socket for zygote command connections
     *
     * @throws RuntimeException when open fails
     */
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                sServerSocket = new LocalServerSocket(
                        createFileDescriptor(fileDesc));
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }
     这里的socketName是在main函数中定义的“zygote”,因此fullSocketName为“ANDROID_SOCKET_zygote”,通过调用System.getenv(fullSocketName)函数,返回在系统环境变量值定义的变量的字符串值;最后根据对应的文件描述符生成一个LocalServerSocket对象,即zygote服务端的Socket,最终该Socket将与ActivityManagerService通信,是java世界启动新进程的通道。

2、预加载Class资源和Resource资源

    在ZygoteInit的main方法中创建完Socket后,便进行预加载资源,这部分功能是通过preload函数完成的,在preload函数中封装了对preloadClasses()和preloadResource()等函数的调用。

    static void preload() {
        Log.d(TAG, "begin preload");
        preloadClasses();
        preloadResources();
        preloadOpenGL();
        preloadSharedLibraries();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();
        Log.d(TAG, "end preload");
    }
2.1、preloadClasses()

    该函数用于加载preloaded-classes文件中指定的java类,代码如下:

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

        InputStream is;
        try {
            is = new FileInputStream(PRELOADED_CLASSES);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
            return;
        }

        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.使用VMRuntime的setTargetHeapUtilization函数可以增强程序堆内存的处理效率。
        float defaultUtilization = runtime.getTargetHeapUtilization();
        runtime.setTargetHeapUtilization(0.8f);

        // Start with a clean slate.
        System.gc();
        runtime.runFinalizationSync();
        Debug.startAllocCounting();//统计两点间的内存分配情况,使用Debug.startAllocCounting()、Debug.stopAllocCounting()

        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 (false) {
                        Log.v(TAG, "Preloading " + line + "...");
                    }
                    Class.forName(line);/*反射机制加载类*/
                    if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
                        if (false) {
                            Log.v(TAG,
                                " GC at " + Debug.getGlobalAllocSize());
                        }
                        System.gc();
                        runtime.runFinalizationSync();
                        Debug.resetGlobalAllocSize();
                    }
                    count++;
                } catch (ClassNotFoundException e) {
                    Log.w(TAG, "Class not found for preloading: " + line);
                } catch (UnsatisfiedLinkError e) {
                    Log.w(TAG, "Problem preloading " + line + ": " + e);
                } catch (Throwable t) {
                    Log.e(TAG, "Error preloading " + line + ".", t);
                    if (t instanceof Error) {
                        throw (Error) t;
                    }
                    if (t instanceof RuntimeException) {
                        throw (RuntimeException) t;
                    }
                    throw new RuntimeException(t);
                }
            }

            Log.i(TAG, "...preloaded " + count + " classes in "
                    + (SystemClock.uptimeMillis()-startTime) + "ms.");
        } catch (IOException e) {
            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
        } finally {
            IoUtils.closeQuietly(is);
            // Restore default.
            runtime.setTargetHeapUtilization(defaultUtilization);

            // Fill in dex caches with classes, fields, and methods brought in by preloading.
            runtime.preloadDexCaches();

            Debug.stopAllocCounting();

            // Bring back root. We'll need it later.还原权限
            setEffectiveUser(ROOT_UID);
            setEffectiveGroup(ROOT_GID);
        }
    }
       其中,PRELOADED_CLASSES是被定义的全局变量“/system/etc/preloaded-classes”,这是一个文件,用来存放预加载的类;根据该文件的内容,我们可以得知函数中读取出来的line便是一个类,通过反射机制加载读取出来的类。preloaded-classes文件中有2000行以上,读取每一行并加载每一行指定的类需要花费较长的时间,这也是影响系统启动速度慢的原因。不过这些类预先加载到内存中,当新的应用程序启动时,可以共享这部分资源,这样便加快了应用程序启动和运行速度。

2.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 {
            System.gc();
            runtime.runFinalizationSync();
            mResources = Resources.getSystem();/*初始化全局变量mResources*/
            mResources.startPreloading();/*设置初始状态,防止重复加载资源*/
            if (PRELOAD_RESOURCES) {/*PRELOAD_RESOURCES设置在zygote初始化时是否加载Resource,初始值为true*/
                Log.i(TAG, "Preloading resources...");

                long startTime = SystemClock.uptimeMillis();
                TypedArray ar = mResources.obtainTypedArray(
                        com.android.internal.R.array.preloaded_drawables);
                int N = preloadDrawables(runtime, ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");

                startTime = SystemClock.uptimeMillis();
                ar = mResources.obtainTypedArray(
                        com.android.internal.R.array.preloaded_color_state_lists);
                N = preloadColorStateLists(runtime, ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");
            }
            mResources.finishPreloading();
        } catch (RuntimeException e) {
            Log.w(TAG, "Failure preloading resources", e);
        } finally {
            Debug.stopAllocCounting();
        }
    }
     preloadResources共加载了两种资源:drawables和color。这些资源定义在frameworks/base/core/res/res/values/array.xml文件中,最终会被编译进frameworks-res.apk中。

3、启动system_server进程

    ZygoteInit的main函数中加载完共享资源后,便开始启动system_server进程,该进程是理解框架层的基础。Android中所有的系统服务都是由该进程启动的,它的异常退出会直接导致zygote“自杀”,这样整个java世界便会崩溃。system_server进程的启动入口是startSystemServer,代码如下:

    /**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_BLOCK_SUSPEND,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server启动system_server的命令行参数 */
        String args[] = {
            "--setuid=1000",/*设置用户ID为1000,即SYSTEM_UID,系统进程*/
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",/*设置进程名*/
            "com.android.server.SystemServer",/*设置要启动的类名*/
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);/*将args数组分解成Arguments类型的对象*/
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process.调用系统函数fork()创建子进程system_server */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);/*在子进程中调用handleSystemServerProcess*/
        }

        return true;/*在父进程中返回*/
    }
       到这里zygote做了第一次分裂,fork出系统服务的总管system_server进程。这个过程分为以下两个重要的步骤:通过forkSystemServer创建system_server子进程;在子进程中调用handleSystemServerProcess方法。

3.1、调用forkSystemServer创建system_server子进程。

    创建system_server的第一步便是调用Zygote类的forkSystemServer方法,该方法位于frameworks/base/core/java/com/android/internal/os/Zygote.java类中,在forkSystemServer方法中通过调用Native方法nativeForkSystemServer来完成启动system_server进程的任务。代码如下:

    /**
     * Special method to start the system server process. In addition to the
     * common actions performed in forkAndSpecialize, the pid of the child
     * process is recorded such that the death of the child process will cause
     * zygote to exit.
     *
     * @param uid the UNIX uid that the new process should setuid() to after
     * fork()ing and and before spawning any threads.
     * @param gid the UNIX gid that the new process should setgid() to after
     * fork()ing and and before spawning any threads.
     * @param gids null-ok; a list of UNIX gids that the new process should
     * setgroups() to after fork and before spawning any threads.
     * @param debugFlags bit flags that enable debugging features.
     * @param rlimits null-ok an array of rlimit tuples, with the second
     * dimension having a length of 3 and representing
     * (resource, rlim_cur, rlim_max). These are set via the posix
     * setrlimit(2) call.
     * @param permittedCapabilities argument for setcap()
     * @param effectiveCapabilities argument for setcap()
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        VM_HOOKS.postForkCommon();
        return pid;
    }
    native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
    nativeForkSystemServer的JNI层代码实现位于/dalvik/vm/native/dalvik_system_Zygote.cpp中,函数名为Dalvik_dalvik_system_Zygote_forkSystemServer,代码如下:
static void Dalvik_dalvik_system_Zygote_forkSystemServer(  
        const u4* args, JValue* pResult)  
{  
    pid_t pid;  
    pid = forkAndSpecializeCommon(args, true); //启动system_server进程  
  
    /* The zygote process checks whether the child process has died or not. */  
    if (pid > 0) {//pid大于0,说明是在父进程中   
        int status;    
  
        ALOGI("System server process %d has been created", pid);  
        gDvm.systemServerPid = pid;  //在虚拟机中记录system_server进程的ID
        /* 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进程   
            ALOGE("System server process %d has died. Restarting Zygote!", pid);  
            kill(getpid(), SIGKILL);//一旦上面的等待返回,说明进程pid(system_server)已终止,此时Zygote杀死自己   
        }  
    }  
    RETURN_INT(pid);  
}  
    该函数的功能主要分为两部分:一是启动system_server进程;二是监控system_server进程的启动结果。system_server进程的启动是由forkAndSpecializeCommon完成的,在forkAndSpecializeCommon函数中调用系统函数fork创建子进程,并且在创建前设置信号处理函数setSignalHandler(),在setSignalHandler方法中调用系统函数sigaction处理SIGCHLD信号(子进程退出信号),指定处理函数sigchldHandler,如果system_server出现异常,就会自杀。

3.2、在子进程中调用handleSystemServerProcess方法

    system_server进程启动之后,便开始执行handleSystemServerProcess方法,代码如下:

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();//关闭fork时从zygote继承下来的socket

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);//设置文件的默认权限

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);//system_server
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
        }

        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
            }

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    null, args);
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }
    在handleSystemServerProcess方法中做了一些清理和初始化工作,接着调用RuntimeInit.zygoteInit方法。

    /**
     * The main function called when started through the zygote process. This
     * could be unified with main(), if the native code in nativeFinishInit()
     * were rationalized with Zygote startup.<p>
     *
     * Current recognized args:
     * <ul>
     *   <li> <code> [--] <start class name>  <args>
     * </ul>
     *
     * @param targetSdkVersion target SDK version
     * @param argv arg strings
     */
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        redirectLogStreams();

        commonInit();
        nativeZygoteInit();

        applicationInit(targetSdkVersion, argv, classLoader);
    }
       在zygoteInit方法中封装了四个方法的调用,对应四个步骤实现不同的初始化操作,分别介绍如下:

    1)、redirectLogStreams方法重定向标准I/O操作,重定向到Android标准的日志系统。

    /**
     * Redirect System.out and System.err to the Android log.
     */
    public static void redirectLogStreams() {
        System.out.close();
        System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
        System.err.close();
        System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
    }
    2)、commonInit方法初始化一些通用设置

    private static final void commonInit() {
        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

        /* set default handler; this applies to all threads in the VM */
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());//设置未捕获异常的默认处理函数

        /*
         * Install a TimezoneGetter subclass for ZoneInfo.db
         */
        TimezoneGetter.setInstance(new TimezoneGetter() {
            @Override
            public String getId() {
                return SystemProperties.get("persist.sys.timezone");
            }
        });
        TimeZone.setDefault(null);

        /*
         * Sets handler for java.util.logging to use Android log facilities.
         * The odd "new instance-and-then-throw-away" is a mirror of how
         * the "java.util.logging.config.class" system property works. We
         * can't use the system property here since the logger has almost
         * certainly already been initialized.
         */
        LogManager.getLogManager().reset();//Android log配置
        new AndroidConfig();

        /*
         * Sets the default HTTP User-Agent used by HttpURLConnection.
         */
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        /*
         * Wire socket tagging to traffic stats.
         */
        NetworkManagementSocketTagger.install();

        /*
         * If we're running in an emulator launched with "-trace", put the
         * VM into emulator trace profiling mode so that the user can hit
         * F9/F10 at any time to capture traces.  This has performance
         * consequences, so it's not something you want to do always.
         */
        String trace = SystemProperties.get("ro.kernel.android.tracing");
        if (trace.equals("1")) {
            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
            Debug.enableEmulatorTraceOutput();
        }

        initialized = true;
    }
    3)、nativeZygoteInit方法开启Binder通信

    nativeZygoteInit是一个native方法,其JNI实现方法位于AndroidRuntime.cpp中,方法名为com_android_internal_os_RuntimeInit_nativiZygoteInit,代码如下:

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

    这里调用onZygoteInit方法,这里onZygoteInit是一个虚函数,直接调用子类AppRuntime.onZygoteInit,代码位于frameworks/base/cmd/app_process/App_main.cpp中。

    virtual void onZygoteInit()
    {
        // Re-enable tracing now that we're no longer in Zygote.
        atrace_set_tracing_enabled(true);

        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//创建PoolThread对象,用于Binder通信
    }
    4)、invokeStaticMain方法抛出异常

    applicationInit方法做了虚拟机设置,并转化了参数后,直接调用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()
     * @param classLoader the classLoader to load {@className} with
     */
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);//利用java反射机制加载类信息,className是com.android.server.SystemServer
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });//加载SystemServer类的main函数
        } 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();//利用java的反射机制,判断main函数的修饰符是否是static和public
        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);//抛出异常
    }
    invokeStaticMain方法利用java的反射机制加载类的信息后,最后抛出一个MethodAndArgsCaller异常,那么在哪里进行的异常捕获呢?

4、执行MethodAndArgsCaller的run方法

    在ZygoteInit的main方法中捕获了MethodAndArgsCaller异常,便执行run方法。

    public static void main(String argv[]) {
        try {
            ......
            registerZygoteSocket(socketName);
            ......
            preload();
            ......
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }

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

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }
   分析下MethodAndArgsCaller类中都做了哪些事情。

    /**
     * Helper exception class which holds a method and arguments and
     * can call them. This is used as part of a trampoline to get rid of
     * the initial process setup stack frames.
     */
    public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {//构造方法中传入了方法和参数
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });//利用java反射机制调用这个方法
            } 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);
            }
        }
    }
    MethodAndArgsCaller类既是一个异常类又是一个线程,异常处理代码中直接调用了这个线程的run方法,并执行了传入的com.android.server.SystemServer类的main方法。invokeStaticMain方法抛出异常的目的是执行com.android.server.SystemServer类的main方法,通过这种方式,可以直接从调用栈中跳出,并返回到ZygoteInit的main方法中。

    system_server绕了一大圈执行了SystemServer的main方法,那么SystemServer又承担了什么使命呢?首先分析一下com.android.server.SystemServer类的main方法中做了哪些事情,代码位于:\frameworks\base\services\java\com\android\server\SystemServer.java,如下:

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    private void run() {
        // 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.
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

        // In case the runtime switched since last boot (such as when
        // the old runtime was removed in an OTA), set the system
        // property so that it is in sync. We can't do this in
        // libnativehelper's JniInvocation::Init code where we already
        // had to fallback to a different runtime because it is
        // running as root and we need to be the system user to set
        // the property. http://b/11463182
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        // Enable the sampling profiler.
        if (SamplingProfilerIntegration.isEnabled()) {//判断是否开启性能统计
            SamplingProfilerIntegration.start();//启动性能统计
            mProfilerSnapshotTimer = new Timer();
            mProfilerSnapshotTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);//结束统计并生成结果文件
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        // Mmmmmm... more memory!申请更多的内存
        VMRuntime.getRuntime().clearGrowthLimit();

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

        // Some devices rely on runtime fingerprint generation, so make sure
        // we've defined it before booting further.
        Build.ensureFingerprintProperty();

        // Within the system server, it is an error to access Environment paths without
        // explicitly specifying a user.
        Environment.setUserRequired(true);

        // Ensure binder calls into the system always run at foreground priority.
        BinderInternal.disableBackgroundScheduling(true);

        // Prepare the main looper thread (this thread).
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

        // Initialize native services.加载libandroid_servers.so库文件
        System.loadLibrary("android_servers");
        nativeInit();

        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();

        // Initialize the system context.
        createSystemContext();

        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

        // Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    nativeInit是本地方法,具体实现位于\frameworks\base\services\core\jni\com_android_server_SystemServer.cpp,只是启动Sensor Service。SensorService是C语言实现的系统服务,因此成为Native System Service。

static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }
}
















    








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值