• Android深入浅出之Zygote


    一 目的

    zygote,是Android搞出来的一个东西。网上讲这个的也非常多。第一次看到这个名字我就挺郁闷,想干嘛这是?Linux下名字都取得挺通俗易懂,深得人心。zygote?不就想模仿Linux下的fork吗?个人觉得Google取名字挺怪,包括Google本身。

    不管怎样,Zygote依然是Android系统的核心,zygote是受精卵的意思,可以认为是Android framework大家族的祖先!我们本节的目的是描述下zygote的来龙去脉,顺便揭露下它的短处,以后大家可以对症下药,变异一个更加优良的品种。

    二 Zygote

    zygote本身是一个应用层的程序,和驱动,内核模块之类的没点关系。这下大家放心点了吧?zygote的启动由linux的祖先init启动。这个在init分析中提过。这里就不说了。

    zygote,ps中看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了”zygote”。不过不影响我们分析。

    zygote的代码在framework/base/cmds/app_process/App_main.cpp中。我们一步步来看。

    既然是应用程序,直接看main咯。

    [---->main]

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

    {

      //参数很重要啊,还记得init分析吗?

    //恩,这几个参数就是:(一定要记住我们的情景分析方法!) 

    //zygote /system/bin/app_process

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

    // These are global variables in ProcessState.cpp

        mArgC = argc;

        mArgV = argv;

       

        mArgLen = 0;

        for (int i=0; i<argc; i++) {

            mArgLen += strlen(argv[i]) + 1;

        }

        mArgLen--;

        AppRuntime runtime;

         //AppRuntime是个什么玩意儿?addVmArguments?好像和虚拟机有点关系喔

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

    [--->AppRuntime]

    class AppRuntime : public AndroidRuntime

    从AndroidRuntime中派生而来,是和dalvik交互的一个方便类,这里先不说了。

    [---->main]

    ...

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

    ....

    if (i < argc) {

            arg = argv[i++];

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

                bool startSystemServer = (i < argc) ?

                        strcmp(argv[i], "--start-system-server") == 0 : false;

               //废话,根据我们的参数,startSystemServer=true

                setArgv0(argv0, "zygote");

              //改名字,不知道windows下的怎么改、linux下的可以用pctrl系统调用

                set_process_name("zygote");

                //start?记住我们的参数

                runtime.start("com.android.internal.os.ZygoteInit",

                    startSystemServer);

            }

        } else {

            return 10;

        }

    FT,app_main还是很简单的,但是runtime.start看起来不简单啊,传进去的那个参数

    “com.android.internal.os.ZygoteInit“挺像java类的命名规则。

    2.1 AppRuntime

    好了,代码进入到runtime.start("com.android.internal.os.ZygoteInit",true)了。source insight直接进去看看。代码在framework/base/core/jni/AppRuntime.cpp中。

    [--->void AndroidRuntime::start()]

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

    {

        LOGD(" >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< ");

        char* slashClassName = NULL;

        char* cp;

        JNIEnv* env;

       //linux下signal的处理,没什么好说的

        blockSigpipe();

       //设置环境变量ANDROID_ROOT为/system

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

        if (rootDir == NULL) {

            rootDir = "/system";

           setenv("ANDROID_ROOT", rootDir, 1);

        }

     

       /*启动虚拟机*/

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

            goto bail;

    启动虚拟机,和JAVA有关系了吧?Android最重要的sdk都是java,那虚拟机这部分肯定要进去看看的。

    [--->int AndroidRuntime::startVm()]

    int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)

    {

    //唉,大部分都是设置java虚拟机的启动参数。不过有几个参数比较重要。

     

    //checkjni,可能没使用过jni的一辈子都不能体会

    //说白了,就是我们在C++层调用jni函数的时候,会对参数或者什么的进行检查

    //要是不合法的话,直接把虚拟机exit!第一个影响速度,第二个是影响程序。

    //这个只作为开发时候使用。

        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;

            }

        }

       //设置虚拟机最大heapsize,才给16M,似乎有点少,尤其是在做图片操作的

      //随便一个几百兆的图片就会把虚拟机搞死。

        strcpy(heapsizeOptsBuf, "-Xmx");

        property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");

        opt.optionString = heapsizeOptsBuf;

        mOptions.add(opt);

     

        LOGD("CheckJNI is %s ", checkJni ? "ON" : "OFF");

        if (checkJni) {

            /* extended JNI checking */

            opt.optionString = "-Xcheck:jni";

            mOptions.add(opt);

     

            /* set a cap on JNI global references */

            opt.optionString = "-Xjnigreflimit:2000";

            mOptions.add(opt);

       }

    //具体dalvik虚拟机有哪些参数,可以参考Dalvik的说明

    //反正调用了下面这个函数,虚拟机就按您指定的参数启动了。

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

            LOGE("JNI_CreateJavaVM failed ");

            goto bail;

        }

     

        result = 0;

     

    bail:

        free(stackTraceFile);

        return result;

    }

    OK,虚拟机起来了,看看我们在runtime.start中还要做什么

    [--->void AndroidRuntime::start()]

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

         ...

    //startReg?

    if (startReg(env) < 0) {

            goto bail;

    }

    看看去。

    [--->int AndroidRuntime::startReg()]

    为何不把startReg改成startRegister()。

    int AndroidRuntime::startReg(JNIEnv* env)

    {

       //这个名字还是很清楚的,设置创建线程的函数为javaCreateThreadEtc

     androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    //JNI知识,自己去查JDK

        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;

    }

    [---->static int 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) {//啥都没干,由传进来的参数控制..浪费我时间。

            return -1;

            }

        }

        return 0;

    }

    回到之前的调用,

    register_jni_procs(gRegJNI, NELEM(gRegJNI), env),它的参数gRegJNI是下面这个结构

    static const RegJNIRec gRegJNI[] = {

        REG_JNI(register_android_debug_JNITest),

        REG_JNI(register_com_android_internal_os_RuntimeInit),

        REG_JNI(register_android_os_SystemClock),

        REG_JNI(register_android_util_EventLog),

        REG_JNI(register_android_util_Log),

    ...后面还有很多,好像是一些函数

    };

    随便挑一个跟进去看看。

    [--->int register_android_debug_JNITest]

    int register_android_debug_JNITest(JNIEnv* env)

    {

        return jniRegisterNativeMethods(env, "android/debug/JNITest",

            gMethods, NELEM(gMethods));

    }

    其实就是注册一些JAVA中native函数在C++层对应的实行函数。

    所以说:

    如果你可以在这个地方加上你定制的东西。

    好了,startReg完了,回到runtime.start。

    [---->void AndroidRuntime::start]

        if (startReg(env) < 0) {

            goto bail;

        }

     

       jclass stringClass;

        jobjectArray strArray;

        jstring classNameStr;

        jstring startSystemServerStr;

      

     

    //下面这些话,都是把c++的字符串转成JAVA的字符串

    //

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

    //构造一个String数组,元素个数为2

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

        classNameStr = env->NewStringUTF(className);

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

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

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

    //java应用程序不也有main函数吗?上面的就是把C++传进来的参数,变成java的参数

    [

      “com.android.internal.os.ZygoteInit”,

      “true”

    ]

        jclass startClass;

        jmethodID startMeth;

       //

         startClass = env->FindClass(slashClassName);

    // 下面这个JNI调用,就真正进入java层了

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

    //下面调用的就是com.android.internal.os.ZygoteInit类的main函数

    //最后一个参数是true

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

    bail:

        free(slashClassName);

    }

    谢谢大家对《深入理解android 卷I/卷II》的支持。
  • 相关阅读:
    ConcurrentSkipListMap 源码分析
    ConcurrentHashMap 源码分析
    CopyOnWriteArrayList 源码分析
    AtomicBoolean 源码分析
    commons-lang3-3.4.jar
    Effective Java
    FindBugs Bug Descriptions
    EasyMock
    Apache Maven 入门
    Eclipse
  • 原文地址:https://www.cnblogs.com/kevincode/p/3940788.html
Copyright © 2020-2023  润新知