一、第一个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 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& 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 (startVm(&mJavaVM, &env) != 0) {        return;    }    /* 开启虚拟机后执行的工作,这里是空函数体,什么都没做。运行时实际调用的是AppRuntime的onVmCreated函数,保存了类的全局引用。*/    onVmCreated(env);    /*     * Register android functions.注册Android JNI函数     */    if (startReg(env) < 0) {        ALOGE("Unable to register all android natives\n");        return;    }    /*     * We want to call main() with a String array with arguments in it.     * At present we have two arguments, the class name and an option string.     * Create an array to hold them.调用指定类的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->CallStaticVoidMethod(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++世界的桥梁。 

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

   

在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.

* * Current recognized args: *

    *
  • [--] *
* * @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 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();    }}
















    








更多相关文章

  1. Android在线更新SDK的方法(使用国内镜像)
  2. 详解Android应用开发中Intent的作用及使用方法
  3. 使用SourceInsight查看android中的native方法
  4. Android设置背景色为透明的两种方法
  5. [置顶] android软键盘弹出,会把原来的界面挤上去的问题 处理方法
  6. Android Button控件 的简单使用(button监听和onClick触发函数使用
  7. android 关于Location of the Android SDK has not been setup i

随机推荐

  1. Android下Animation动画的使用 及 Volley
  2. android登录界面
  3. android RelativeLayout常用xml布局属性
  4. Android实现判断某个服务是否正在运行的
  5. AR(Argumented Reality)技术汇总
  6. Android控件之ToggleButton(多状态按钮)
  7. Android(安卓)“adb forward”端口映射
  8. Android(安卓)调用系统拍照 笔记 - 会说
  9. Parcelable和Parcel
  10. Attribute is missing the Android(安卓)