美文网首页Android开发程序员技术栈IT@程序员猿媛
Android系统启动之zyogte进程java(上)

Android系统启动之zyogte进程java(上)

作者: Lee_5566 | 来源:发表于2019-03-29 17:09 被阅读5次
    image.png

    目录

    第一篇:Android系统启动之bootloader
    第二篇:Android系统启动之Init流程(上)
    第三篇:Android系统启动之Init流程(下)
    第四篇:Android系统启动之init.rc文件解析过程
    第五篇:Android系统启动之zyogte进程
    第六篇:Android系统启动之zyogte进程java(上)

    AppRuntime类

    上篇文章提到,其实最后创建虚拟机的就是这个类.

    这个类在android系统中十分重要.

    AndroidRuntime类是安卓底层系统超级重要的一个类,它负责启动虚拟机以及Java线程。AndroidRuntime类是在一个进程中只有一个实例对象,并将其保存在全局变量gCurRuntime中

    AppRuntime类构造函数:

    AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
            mExitWithoutCleanup(false),
            mArgBlockStart(argBlockStart),
            mArgBlockLength(argBlockLength)
    {
        //初始化skia图形系统
        SkGraphics::Init();
        // There is also a global font cache, but its budget is specified by
        // SK_DEFAULT_FONT_CACHE_COUNT_LIMIT and SK_DEFAULT_FONT_CACHE_LIMIT.
    
        //预先分配空间来存放传入虚拟机的参数
        // Pre-allocate enough space to hold a fair number of options.
        mOptions.setCapacity(20);
    
        //断言判断gCurRuntime是否为空,保证只能被初始化一次
        assert(gCurRuntime == NULL);        // one per process
        gCurRuntime = this;
    }
    

    构造函数主要做的事情:
    1. 初始化skia图形系统
    2. 预先分配空间来存放传入虚拟机的参数
    3. 断言判断gCurRuntime是否为空,保证只能被初始化一次

    注:skia是google的第一个底层的图形、图像、动画、SVG、文本等多方面的图形图,是Android图形系统的引擎。skia作为第三方软件放在external目录下: external/skia/。

    start函数

    然后便会调用start函数:

    /*
     * Start the Android runtime.  This involves starting the virtual machine
     * and calling the "static void main(String[] args)" method in the class
     * named by "className".
     *
     * Passes the main function two arguments, the class name and the specified
     * options string.
     */
    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        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, zygote) != 0) {
            return;
        }
    //******************* 第四部分**********************************************
        onVmCreated(env);
    //******************* 第五部分**********************************************
        /*
         * Register android functions.
         */
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
    //******************* 第六部分**********************************************
        /*
         * We want to call main() with a String array with arguments in it.
         * At present we have two arguments, the class name and an option string.
         * Create an array to hold them.
         */
        jclass stringClass;
        jobjectArray strArray;
        jstring classNameStr;
    
        stringClass = env->FindClass("java/lang/String");
        assert(stringClass != NULL);
        strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
        assert(strArray != NULL);
        classNameStr = env->NewStringUTF(className);
        assert(classNameStr != NULL);
        env->SetObjectArrayElement(strArray, 0, classNameStr);
    
        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);
        }
    //******************* 第七部分**********************************************
        /*
         * Start VM.  This thread becomes the main thread of the VM, and will
         * not return until the VM exits.
         */
        char* slashClassName = toSlashClassName(className);
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
            /* keep going */
        } else {
            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 {
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
    
    #if 0
                if (env->ExceptionCheck())
                    threadExitUncaughtException(env);
    #endif
            }
        }
        free(slashClassName);
    
        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");
    }
    
    void AndroidRuntime::exit(int code)
    {
        if (mExitWithoutCleanup) {
            ALOGI("VM exiting with result code %d, cleanup skipped.", code);
            ::_exit(code);
        } else {
            ALOGI("VM exiting with result code %d.", code);
            onExit(code);
            ::exit(code);
        }
    }
    

    start函数主要做了七件事:
    1. 判断是否是启动systemServer。
    2. 从环境变量ANDROID_ROOT中读取系统目录。
    3. 初始化jni接口, 并启动虚拟机, 即调用startVm函数。
    4. 调用onVimCreate()函数. 该函数是一个虚函数,调用它实际上调用的是继承类的AppRuntime中的重载函数。
    5. 注册系统的JNI函数
    6. 准备启动Java类的main函数的环境
    7. 启动Zygoteinit类的main()函数(java)

    到这里就将Zygoet的初始化将转移到Java。O(∩_∩)O哈哈~

    附上启动虚拟机的代码

    /*
     * 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, bool zygote)
    {
        JavaVMInitArgs initArgs;
        char propBuf[PROPERTY_VALUE_MAX];
        char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
        char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
        char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
        char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
        char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
        char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
        char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
        char usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX];
        char jitmaxsizeOptsBuf[sizeof("-Xjitmaxsize:")-1 + PROPERTY_VALUE_MAX];
        char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];
        char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];
        char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];
        char jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];
        char jittransitionweightOptBuf[sizeof("-Xjittransitionweight:")-1 + PROPERTY_VALUE_MAX];
        char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
        char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
        char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
        char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
        char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
        char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
        char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
        char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
        char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
        char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];
        char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
        char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX];
        char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
        char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
        char extraOptsBuf[PROPERTY_VALUE_MAX];
        char voldDecryptBuf[PROPERTY_VALUE_MAX];
        enum {
          kEMDefault,
          kEMIntPortable,
          kEMIntFast,
          kEMJitCompiler,
        } executionMode = kEMDefault;
        char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];
        char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
        char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
        char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX];
        char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];
        char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
        char fingerprintBuf[sizeof("-Xfingerprint:") + PROPERTY_VALUE_MAX];
    
        bool checkJni = false;
        property_get("dalvik.vm.checkjni", propBuf, "");
        if (strcmp(propBuf, "true") == 0) {
            checkJni = true;
        } else if (strcmp(propBuf, "false") != 0) {
            /* property is neither true nor false; fall back on kernel parameter */
            property_get("ro.kernel.android.checkjni", propBuf, "");
            if (propBuf[0] == '1') {
                checkJni = true;
            }
        }
        ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
        if (checkJni) {
            /* extended JNI checking */
            addOption("-Xcheck:jni");
    
            /* with -Xcheck:jni, this provides a JNI function call trace */
            //addOption("-verbose:jni");
        }
    
        property_get("dalvik.vm.execution-mode", propBuf, "");
        if (strcmp(propBuf, "int:portable") == 0) {
            executionMode = kEMIntPortable;
        } else if (strcmp(propBuf, "int:fast") == 0) {
            executionMode = kEMIntFast;
        } else if (strcmp(propBuf, "int:jit") == 0) {
            executionMode = kEMJitCompiler;
        }
    
        parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
    
        strcpy(jniOptsBuf, "-Xjniopts:");
        if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {
            ALOGI("JNI options: '%s'\n", jniOptsBuf);
        }
    
        /* route exit() to our handler */
        addOption("exit", (void*) runtime_exit);
    
        /* route fprintf() to our handler */
        addOption("vfprintf", (void*) runtime_vfprintf);
    
        /* register the framework-specific "is sensitive thread" hook */
        addOption("sensitiveThread", (void*) runtime_isSensitiveThread);
    
        /* enable verbose; standard options are { jni, gc, class } */
        //addOption("-verbose:jni");
        addOption("-verbose:gc");
        //addOption("-verbose:class");
    
        /*
         * The default starting and maximum size of the heap.  Larger
         * values should be specified in a product property override.
         */
        parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
        parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
    
        parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
        parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
        parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
        parseRuntimeOption("dalvik.vm.heaptargetutilization",
                           heaptargetutilizationOptsBuf,
                           "-XX:HeapTargetUtilization=");
    
        /*
         * JIT related options.
         */
        parseRuntimeOption("dalvik.vm.usejit", usejitOptsBuf, "-Xusejit:");
        parseRuntimeOption("dalvik.vm.jitmaxsize", jitmaxsizeOptsBuf, "-Xjitmaxsize:");
        parseRuntimeOption("dalvik.vm.jitinitialsize", jitinitialsizeOptsBuf, "-Xjitinitialsize:");
        parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:");
        property_get("dalvik.vm.usejitprofiles", useJitProfilesOptsBuf, "");
        if (strcmp(useJitProfilesOptsBuf, "true") == 0) {
            addOption("-Xjitsaveprofilinginfo");
        }
    
        parseRuntimeOption("dalvik.vm.jitprithreadweight",
                           jitprithreadweightOptBuf,
                           "-Xjitprithreadweight:");
    
        parseRuntimeOption("dalvik.vm.jittransitionweight",
                           jittransitionweightOptBuf,
                           "-Xjittransitionweight:");
    
        property_get("ro.config.low_ram", propBuf, "");
        if (strcmp(propBuf, "true") == 0) {
          addOption("-XX:LowMemoryMode");
        }
    
        parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
        parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
    
        /*
         * Enable debugging only for apps forked from zygote.
         * Set suspend=y to pause during VM init and use android ADB transport.
         */
        if (zygote) {
          addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y");
        }
    
        parseRuntimeOption("dalvik.vm.lockprof.threshold",
                           lockProfThresholdBuf,
                           "-Xlockprofthreshold:");
    
        if (executionMode == kEMIntPortable) {
            addOption("-Xint:portable");
        } else if (executionMode == kEMIntFast) {
            addOption("-Xint:fast");
        } else if (executionMode == kEMJitCompiler) {
            addOption("-Xint:jit");
        }
    
        // If we are booting without the real /data, don't spend time compiling.
        property_get("vold.decrypt", voldDecryptBuf, "");
        bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
                                 (strcmp(voldDecryptBuf, "1") == 0));
    
        // Extra options for boot.art/boot.oat image generation.
        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
                                   "-Xms", "-Ximage-compiler-option");
        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
                                   "-Xmx", "-Ximage-compiler-option");
        if (skip_compilation) {
            addOption("-Ximage-compiler-option");
            addOption("--compiler-filter=assume-verified");
        } else {
            parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
                                "--compiler-filter=", "-Ximage-compiler-option");
        }
    
        // Make sure there is a preloaded-classes file.
        if (!hasFile("/system/etc/preloaded-classes")) {
            ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
                  strerror(errno));
            return -1;
        }
        addOption("-Ximage-compiler-option");
        addOption("--image-classes=/system/etc/preloaded-classes");
    
        // If there is a compiled-classes file, push it.
        if (hasFile("/system/etc/compiled-classes")) {
            addOption("-Ximage-compiler-option");
            addOption("--compiled-classes=/system/etc/compiled-classes");
        }
    
        property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
        parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
    
        // Extra options for DexClassLoader.
        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
                                   "-Xms", "-Xcompiler-option");
        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
                                   "-Xmx", "-Xcompiler-option");
        if (skip_compilation) {
            addOption("-Xcompiler-option");
            addOption("--compiler-filter=assume-verified");
    
            // We skip compilation when a minimal runtime is brought up for decryption. In that case
            // /data is temporarily backed by a tmpfs, which is usually small.
            // If the system image contains prebuilts, they will be relocated into the tmpfs. In this
            // specific situation it is acceptable to *not* relocate and run out of the prebuilts
            // directly instead.
            addOption("--runtime-arg");
            addOption("-Xnorelocate");
        } else {
            parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
                                "--compiler-filter=", "-Xcompiler-option");
        }
        parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");
        parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j",
                            "-Ximage-compiler-option");
    
        // The runtime will compile a boot image, when necessary, not using installd. Thus, we need to
        // pass the instruction-set-features/variant as an image-compiler-option.
        // TODO: Find a better way for the instruction-set.
    #if defined(__arm__)
        constexpr const char* instruction_set = "arm";
    #elif defined(__aarch64__)
        constexpr const char* instruction_set = "arm64";
    #elif defined(__mips__) && !defined(__LP64__)
        constexpr const char* instruction_set = "mips";
    #elif defined(__mips__) && defined(__LP64__)
        constexpr const char* instruction_set = "mips64";
    #elif defined(__i386__)
        constexpr const char* instruction_set = "x86";
    #elif defined(__x86_64__)
        constexpr const char* instruction_set = "x86_64";
    #else
        constexpr const char* instruction_set = "unknown";
    #endif
        // Note: it is OK to reuse the buffer, as the values are exactly the same between
        //       * compiler-option, used for runtime compilation (DexClassLoader)
        //       * image-compiler-option, used for boot-image compilation on device
    
        // Copy the variant.
        sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
        parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
                            "--instruction-set-variant=", "-Ximage-compiler-option");
        parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
                            "--instruction-set-variant=", "-Xcompiler-option");
        // Copy the features.
        sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
        parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
                            "--instruction-set-features=", "-Ximage-compiler-option");
        parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
                            "--instruction-set-features=", "-Xcompiler-option");
    
    
        property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
        parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
    
        /* extra options; parse this late so it overrides others */
        property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
        parseExtraOpts(extraOptsBuf, NULL);
    
        /* Set the properties for locale */
        {
            strcpy(localeOption, "-Duser.locale=");
            const std::string locale = readLocale();
            strncat(localeOption, locale.c_str(), PROPERTY_VALUE_MAX);
            addOption(localeOption);
        }
    
        // Trace files are stored in /data/misc/trace which is writable only in debug mode.
        property_get("ro.debuggable", propBuf, "0");
        if (strcmp(propBuf, "1") == 0) {
            property_get("dalvik.vm.method-trace", propBuf, "false");
            if (strcmp(propBuf, "true") == 0) {
                addOption("-Xmethod-trace");
                parseRuntimeOption("dalvik.vm.method-trace-file",
                                   methodTraceFileBuf,
                                   "-Xmethod-trace-file:");
                parseRuntimeOption("dalvik.vm.method-trace-file-siz",
                                   methodTraceFileSizeBuf,
                                   "-Xmethod-trace-file-size:");
                property_get("dalvik.vm.method-trace-stream", propBuf, "false");
                if (strcmp(propBuf, "true") == 0) {
                    addOption("-Xmethod-trace-stream");
                }
            }
        }
    
        // Native bridge library. "0" means that native bridge is disabled.
        property_get("ro.dalvik.vm.native.bridge", propBuf, "");
        if (propBuf[0] == '\0') {
            ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
        } else if (strcmp(propBuf, "0") != 0) {
            snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
                     "-XX:NativeBridge=%s", propBuf);
            addOption(nativeBridgeLibrary);
        }
    
    #if defined(__LP64__)
        const char* cpu_abilist_property_name = "ro.product.cpu.abilist64";
    #else
        const char* cpu_abilist_property_name = "ro.product.cpu.abilist32";
    #endif  // defined(__LP64__)
        property_get(cpu_abilist_property_name, propBuf, "");
        if (propBuf[0] == '\0') {
            ALOGE("%s is not expected to be empty", cpu_abilist_property_name);
            return -1;
        }
        snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf);
        addOption(cpuAbiListBuf);
    
        // Dalvik-cache pruning counter.
        parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
                           "-Xzygote-max-boot-retry=");
    
        /*
         * When running with debug.generate-debug-info, add --generate-debug-info to
         * the compiler options so that the boot image, if it is compiled on device,
         * will include native debugging information.
         */
        property_get("debug.generate-debug-info", propBuf, "");
        if (strcmp(propBuf, "true") == 0) {
            addOption("-Xcompiler-option");
            addOption("--generate-debug-info");
            addOption("-Ximage-compiler-option");
            addOption("--generate-debug-info");
        }
    
        /*
         * Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will
         * contain the fingerprint and can be parsed.
         */
        parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:");
    
        initArgs.version = JNI_VERSION_1_4;
        initArgs.options = mOptions.editArray();
        initArgs.nOptions = mOptions.size();
        initArgs.ignoreUnrecognized = JNI_FALSE;
    
        /*
         * Initialize the VM.
         *
         * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
         * If this call succeeds, the VM is ready, and we can start issuing
         * JNI calls.
         */
        if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
            ALOGE("JNI_CreateJavaVM failed\n");
            return -1;
        }
    
        return 0;
    }
    
    char* AndroidRuntime::toSlashClassName(const char* className)
    {
        char* result = strdup(className);
        for (char* cp = result; *cp != '\0'; cp++) {
            if (*cp == '.') {
                *cp = '/';
            }
        }
        return result;
    }
    

    Java层ZygoteInit的main

    代码路径frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    main函数的主要作用就是启动SystemServer服务,并用socket监听.

    下面分析下源码:

       public static void main(String argv[]) {
     //**************** 第一部分 **********************
            ZygoteServer zygoteServer = new ZygoteServer();
    
            // Mark zygote start. This ensures that thread creation will throw
            // an error.
            ZygoteHooks.startZygoteNoThreadCreation();
    
            // Zygote goes into its own process group.
            try {
                Os.setpgid(0, 0);
            } catch (ErrnoException ex) {
                throw new RuntimeException("Failed to setpgid(0,0)", ex);
            }
    
            try {
                // Report Zygote start time to tron unless it is a runtime restart
                if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                    MetricsLogger.histogram(null, "boot_zygote_init",
                            (int) SystemClock.elapsedRealtime());
                }
    
                String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
                BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,
                        Trace.TRACE_TAG_DALVIK);
                bootTimingsTraceLog.traceBegin("ZygoteInit");
                RuntimeInit.enableDdms();
                // Start profiling the zygote initialization.
                SamplingProfilerIntegration.start();
    
                boolean startSystemServer = false;
                String socketName = "zygote";
                String abiList = null;
                boolean enableLazyPreload = false;
                for (int i = 1; i < argv.length; i++) {
                    if ("start-system-server".equals(argv[i])) {
                        startSystemServer = true;
                    } else if ("--enable-lazy-preload".equals(argv[i])) {
                        enableLazyPreload = 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.");
                }
    
                zygoteServer.registerServerSocket(socketName);
                // In some configurations, we avoid preloading resources and classes eagerly.
                // In such cases, we will preload things prior to our first fork.
                if (!enableLazyPreload) {
                    bootTimingsTraceLog.traceBegin("ZygotePreload");
                    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                    preload(bootTimingsTraceLog);
                    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                    bootTimingsTraceLog.traceEnd(); // ZygotePreload
                } else {
                    Zygote.resetNicePriority();
                }
     //**************** 第三部分 **********************
                // Finish profiling the zygote initialization.
                SamplingProfilerIntegration.writeZygoteSnapshot();
    
                // Do an initial gc to clean up after startup
                bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
                gcAndFinalize();
                bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
    
                bootTimingsTraceLog.traceEnd(); // ZygoteInit
                // Disable tracing so that forked processes do not inherit stale tracing tags from
                // Zygote.
                Trace.setTracingEnabled(false);
    
                // Zygote process unmounts root storage spaces.
                Zygote.nativeUnmountStorageOnInit();
    
                // Set seccomp policy
                Seccomp.setPolicy();
    
                ZygoteHooks.stopZygoteNoThreadCreation();
     //**************** 第四部分 **********************
                if (startSystemServer) {
                    startSystemServer(abiList, socketName, zygoteServer);
                }
     //**************** 第五部分 **********************
                Log.i(TAG, "Accepting command socket connections");
                zygoteServer.runSelectLoop(abiList);
    
                zygoteServer.closeServerSocket();
            } catch (Zygote.MethodAndArgsCaller caller) {
                caller.run();
            } catch (Throwable ex) {
                Log.e(TAG, "System zygote died with exception", ex);
                zygoteServer.closeServerSocket();
                throw ex;
            }
        }
    

    源码功能大致分为五个部分:
    1. 解析调用的参数,即argv[]
    2.初始化zygoteServer,并注册Zygote的socket监听接口
    3.装载系统资源,
    4.startSystemServer()方法启动SystemServer进程
    5.进入监听和接收消息的循环

    到这里就是启动了java层.O(∩_∩)O哈哈~

    参考

    Android系统启动——4 zyogte进程 (C篇)
    Android系统启动——5 zyogte进程(Java篇)

    相关文章

      网友评论

        本文标题:Android系统启动之zyogte进程java(上)

        本文链接:https://www.haomeiwen.com/subject/bzvtbqtx.html