美文网首页
Zygote——Native

Zygote——Native

作者: 开开向前冲 | 来源:发表于2017-08-22 16:13 被阅读0次

    版权说明:本文为 开开向前冲 原创文章,转载请注明出处;
    注:限于作者水平有限,文中有不对的地方还请指教

    我刚开始接触Android 是作为一名APP开发者,因此在刚开始看到 Zygote 时,并不明白它是什么,
    现在我在这里记录一下自己对于 Zygote 的理解;

    Zygote —— 进程起源地

    1.Zygote 启动:init.zygote32.rc

    /system/core/rootdir/init.zygote32.rc

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart media
        onrestart restart netd
    

    /system/bin/app_process是Zygote进程的可执行程序,后续都是启动参数;
    app_process的源码路径:

    /frameworks/base/cmds/app_process/app_main.cpp
    

    1-1. main方法

    int main(int argc, char* const argv[])
    {
        if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {//Selinux相关,防止动态更改权限
            // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
            // EINVAL. Don't die on such kernels.
            if (errno != EINVAL) { //老版本内核一直返回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[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 = true;
                niceName = ZYGOTE_NICE_NAME;
            } else if (strcmp(arg, "--start-system-server") == 0) {
                startSystemServer = true;
            } else if (strcmp(arg, "--application") == 0) {
                application = true;
            } else if (strncmp(arg, "--nice-name=", 12) == 0) {
                niceName.setTo(arg + 12);
            } else if (strncmp(arg, "--", 2) != 0) {
                className.setTo(arg);
                break;
            } else {
                --i;
                break;
            }
        }
    
        Vector<String8> args;
        if (!className.isEmpty()) {
            // We're not in zygote mode, the only argument we need to pass
            // to RuntimeInit is the application argument.
            //
            // The Remainder of args get passed to startup class main(). Make
            // copies of them before we overwrite them with the process name.
            args.add(application ? String8("application") : String8("tool"));
            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());
        }
    
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        } else if (className) {
            runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
        } 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;
        }
    }
    

    对于init.zygote32.rc中service Zygote 的参数已经在main方法的注释中都有讲解;

    " -Xzygote"是VM参数;
    "/system/bin"是可执行程序app_process的父目录,可以不关注;
    "--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.

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    第一个参数从"/system/bin/app_process"算起,argc = 5(参数长度),argv = argv[0] = "/system/bin/app_process"

        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        // Process command line arguments
        // ignore argv[0]
        argc--; //参数个数减一
        argv++; //指向argv[1]
    

    上述代码执行完成后,

    argc = 4 argv指向参数原始参数的argv[1],即argv = "-Xzygote"

    上面忽略第一个参数的原因相比你已经了解——当实参传给main函数之后,argv的第一个元素指向程序的名字或者一个空字符串,接下来的元素依次传递给命令行提供的实参,最后一个指针之后的元素保证为0。

    接下来是一个循环

    int i;
        for (i = 0; i < argc; i++) { 
            if (argv[i][0] != '-') { //argv[i]是一个字符串数组,所以此时是判断参数头部是否带有"-"
                break;
            }
            if (argv[i][1] == '-' && argv[i][2] == 0) {
                ++i; // Skip --. 
                break;
            }
            runtime.addOption(strdup(argv[i]));//这个循环的核心就是执行这段代码,从判断条件中知道
                        //只有 "-Xzygote"符合要求,即给虚拟机设置参数
        }
    

    上述代码循环是在判断第二个参数时退出的,循环退出时i = 1,argc = 4

        // 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. //此时i = 2
        while (i < argc) { //argc = 4
            const char* arg = argv[i++]; //从argv[2]开始算起,即跳过了/system/bin
            if (strcmp(arg, "--zygote") == 0) {
                zygote = true;
                niceName = ZYGOTE_NICE_NAME;
            } else if (strcmp(arg, "--start-system-server") == 0) {
                startSystemServer = true;
            } else if (strcmp(arg, "--application") == 0) {
                application = true;
            } else if (strncmp(arg, "--nice-name=", 12) == 0) {
                niceName.setTo(arg + 12);
            } else if (strncmp(arg, "--", 2) != 0) {
                className.setTo(arg);
                break;
            } else {
                --i;
                break;
            }
        }
    

    上述这段代码很简单,就是根据传递的argv参数来设置几个变量,后续肯定会根据这个几个变量来执行相关操作;一共循环两次,上述代码执行完成后i = 4,但是argv的指向-Xzygote;循环结束后,变量的值如下:
    zygote = true;
    niceName = ZYGOTE_NICE_NAME;
    startSystemServer = true;

    循环结束后会根据上述赋值的变量来进行一些初始化操作,代码如下:

    Vector<String8> args; //该变量后续会作为AppRuntime 的启动参数传递
        if (!className.isEmpty()) {   //className 在上述代码中没有赋值,所以className 为空
            // 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"));
            runtime.setClassNameAndArgs(className, argc - i, argv + i);
        } else { //className 为空,走该流程==================>>
            // We're in zygote mode.
            maybeCreateDalvikCache(); //创建虚拟机Cache 文件,目录在/data/dalvik-cache/下,
    // 我的机器是arm架构,所以在这个目录下生成一个arm的文件夹,里面存放的都是一些dex文件;
    
            if (startSystemServer) {
                args.add(String8("start-system-server"));//添加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());
        }
    

    1-2. maybeCreateDalvikCache() 方法

    static void maybeCreateDalvikCache() {
    #if defined(__aarch64__)
        static const char kInstructionSet[] = "arm64";
    #elif defined(__x86_64__)
        static const char kInstructionSet[] = "x86_64";
    #elif defined(__arm__)
        static const char kInstructionSet[] = "arm";
    #elif defined(__i386__)
        static const char kInstructionSet[] = "x86";
    #elif defined (__mips__)
        static const char kInstructionSet[] = "mips";
    #else
    #error "Unknown instruction set"
    #endif
        const char* androidRoot = getenv("ANDROID_DATA");
        LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset");
    
        char dalvikCacheDir[PATH_MAX];
        const int numChars = snprintf(dalvikCacheDir, PATH_MAX,
                "%s/dalvik-cache/%s", androidRoot, kInstructionSet);//dalvikCacheDir最终为/data/dalvik-cache/arm
        LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
                "Error constructing dalvik cache : %s", strerror(errno));
    
        int result = mkdir(dalvikCacheDir, 0711);
        LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST),
                "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno));
    
        // We always perform these steps because the directory might
        // already exist, with wider permissions and a different owner
        // than we'd like.
        result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT);//修改用户和用户主组为ROOT
        LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno));
    
        result = chmod(dalvikCacheDir, 0711);
        LOG_ALWAYS_FATAL_IF((result < 0),
                "Error changing dalvik-cache permissions : %s", strerror(errno));
    }
    

    maybeCreateDalvikCache 完成的功能如下:

    1. 设置虚拟机指令集;
    2. 创建虚拟机缓存目录;目录为/data/dalvik-cache/arm,后面的arm是根据签名机器指令集赋值的;我的机器为arm;
    3. 修改目录的USER和GROUP 为ROOT 用户;
    4. 修改目录权限为"0711"(-rwx--x--x),即目录拥有者有读写执行权限,其他用户只有执行权限;
    

    maybeCreateDalvikCache 后:

            if (startSystemServer) {
                args.add(String8("start-system-server"));
            }
            char prop[PROP_VALUE_MAX];
            if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { //根据ABI_LIST_PROPERTY属性获取abi-list参数
                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);// 添加abi-list参数
    
            // In zygote mode, pass all remaining arguments to the zygote
            // main() method.
            for (; i < argc; ++i) { //开机执行这句代码前i = 4,argc = 4,所以下面程序不会执行,  
                                    //即没有参数需要添加了,如果还有参数会接着添加
                args.add(String8(argv[i]));//将参数添加到args,再传给Runtime
            }
        ......
        ......
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args);//启动ZygoteInit,接收上面传递过来的参数args,
                                                                      //即从init.rc传递过来的参数;
        } else if (className) {
            runtime.start("com.android.internal.os.RuntimeInit", args);//调用AndroidRuntime的start方法
                                                                       //启动RuntimeInit
        } 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;
        }
    

    注:这里所说的过程是第一次开机Zygote 的处理过程,参数也是开机过程从init.rc中传递的参数,我尝试使用adb install 安装应用,也会调用Zygote,但是参数和上述描述不一样;

    到此app_main的main方法执行结束,程序将继续执行AndroidRuntime的start方法;

    2. AndroidRuntime

    frameworks/base/core/jni/AndroidRuntime.cpp

    2-1. AndroidRuntime::start(const char* className, const Vector<String8>& options)
    /*
     * 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)
    {
        ALOGD(">>>>>> START %s uid %d <<<<<<\n",
                className != NULL ? className : "(unknown)", getuid());
    
        static const String8 startSystemServer("start-system-server");//初始化字符串startSystemServer,
                                                    //判断从app_main传递过来的参数是否带有该参数
    
        /*
         * '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");//获取ANDROID_ROOT环境变量,
              //adb shell 到手机里面echo $ANDROID_ROOT,得出该环境变量为 "/system"
        if (rootDir == NULL) {//第一次进来为空,先设置rootDir 为"/system"
            rootDir = "/system";
            if (!hasDir("/system")) {
                LOG_FATAL("No root directory specified, and /android does not exist.");
                return;
            }
            setenv("ANDROID_ROOT", rootDir, 1);
        }
    
        //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
        //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
    
        /* start the virtual machine */
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
        if (startVm(&mJavaVM, &env) != 0) { //核心,启动虚拟机,该方法中会配置各种JVM参数,
                    //最终会调用JNI_CreateJavaVM方法创建JVM
            return;
        }
        onVmCreated(env);
    
        /*
         * Register android functions.
         */
        if (startReg(env) < 0) {//核心中的核心,注册JNI方法,什么Binder,各种核心库的JNI基本都在这里注册
            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);//className从app_main.cpp传递过来的,
                        //为"com.android.internal.os.ZygoteInit",
                        //toSlashClassName将className中的字符串替换为"/"来满足FindClass(slashClassName)
                        //对参数的需求来获取java class 对象
        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");  //获取Java层ZygoteInit的"main"方法ID
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
                /* keep going */
            } else {
                env->CallStaticVoidMethod(startClass, startMeth, strArray);//执行Java层ZygoteInit "main"方法,
                //终于看到了指向Java层的曙光;
    
    #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");
    }
    

    本来我们应该继续往下跳转到ZygoteInit.java的main方法,但是我觉得AndroidRuntime中有几个重要的方法需要记住,在此先说说,Java层的ZygoteInit放到下一篇再说:

    2-2. int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
    /*
     * 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 zygoteMaxFailedBootsBuf[sizeof("-XzygoteMaxFailedBoots")-1 + PROPERTY_VALUE_MAX];
        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];
        ......
        property_get("dalvik.vm.checkjni", propBuf, "");
        ......
        parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
        ......
    }
    
    /*
     * Reads a "property" into "buffer" with a default of "defaultArg". If
     * the property is non-empty, it is treated as a runtime option such
     * as "-Xmx32m".
     *
     * The "runtimeArg" is a prefix for the option such as "-Xms" or "-Xmx".
     *
     * If an argument is found, it is added to mOptions.
     *
     * If an option is found, it is added to mOptions and true is
     * returned. Otherwise false is returned.
     */
    bool AndroidRuntime::parseRuntimeOption(const char* property,
                                            char* buffer,
                                            const char* runtimeArg,
                                            const char* defaultArg)
    {
        strcpy(buffer, runtimeArg);
        size_t runtimeArgLen = strlen(runtimeArg);
        property_get(property, buffer+runtimeArgLen, defaultArg);
        if (buffer[runtimeArgLen] == '\0') {
            return false;
        }
        addOption(buffer);
        return true;
    }
    

    这里对于Java Dalvik 参数配置,大部分都是通过获取系统属性来赋值;对此不需要详解;

    2-3. int AndroidRuntime::startReg(JNIEnv* env)
    /*
     * 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) {//注册JNI方法,很重要,gRegJNI是方法表
            env->PopLocalFrame(NULL);
            return -1;
        }
        env->PopLocalFrame(NULL);
    
        //createJavaThread("fubar", quickTest, (void*) "hello");
    
        return 0;
    }
    

    2-4. gRegJNI 方法表

    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_os_Process),
        REG_JNI(register_android_os_SystemProperties),
        REG_JNI(register_android_os_Binder),
        REG_JNI(register_android_os_Parcel),
        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_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_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_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_NetworkUtils),
        REG_JNI(register_com_android_internal_os_ZygoteInit),
        REG_JNI(register_com_android_internal_os_Zygote),
        REG_JNI(register_android_hardware_Camera),
        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_media_AudioRecord),
        REG_JNI(register_android_media_AudioSystem),
        REG_JNI(register_android_media_AudioTrack),
        REG_JNI(register_android_media_ToneGenerator),
    
        REG_JNI(register_android_opengl_classes),
        REG_JNI(register_android_server_NetworkManagementSocketTagger),
        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),
    };
    

    限于篇幅原因我删除了很多,这里注册的这些JNI方法都很重要很重要很重要,比如Binder,Camera,EGL 等等;

    这篇文章描述有点杂,贴的代码中有很多注释,很多是Google 原生的注释我没删除,因为我觉得这些注释简单明了。

    总结:app_process进程主要是根据init.rc脚本来设置参数,然后调用到Java层的ZygoteInit;

    相关文章

      网友评论

          本文标题:Zygote——Native

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