Android ---- Zygote 深入

Zygote 启动: 

1, init.rc  启动 zygote :

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

2, app_process 即: framework/base/cmds/app_process/App_main.cpp  : ----- main 中 AndroidRuntime的 start 调用

            set_process_name("zygote");
            runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer);

      由于:

class AppRuntime : public AndroidRuntime

      继承关系,调用的是 AndroidRuntime的start 函数:

void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
    // 设置 ANDROID_ROOT  为/system
    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.");
            goto bail;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

     // 启动虚拟机
    /* start the virtual machine */
    if (startVm(&mJavaVM, &env) != 0)
        goto bail;
}


 ------------- 调用 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\n", 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\n");

        goto bail;

    }

 
    result = 0;

 
bail:

    free(stackTraceFile);

    return result;

}


3, 在  启动虚拟机后,调用 startReg() 注册Android 函数:

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

    LOGV("--- 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;
}

 

 上述register_jni_procs()就是注册 : gRegJNI全局变量的函数:  frameworks/base/core/jni/AndroidRuntime.cpp 

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),
    REG_JNI(register_android_util_FloatMath),
    REG_JNI(register_android_text_format_Time),
    REG_JNI(register_android_pim_EventRecurrence),
    ....
  }


上述注册的函数,提供JAVA调用native函数。

 

4, 在调用完上述的StartReg函数后,即将进入到JAVA世界:

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

}

 

进入到: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java  中的main() 函数

跑完AndroidRuntime.cpp的start(...) 函数后,跳到ZygoteInit.java的main()函数

  public static void main(String argv[]) {
        try {
            VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);

            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

	//注册 zygote的端口
            registerZygoteSocket();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
	//预加载一些类。
            preloadClasses();
            //cacheRegisterMaps();
	//预加载一些资源文件
            preloadResources();
            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();

            // If requested, start system server directly from Zygote
            if (argv.length != 2) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

            if (argv[1].equals("true")) {
	//启动Systemserver
                startSystemServer();
            } else if (!argv[1].equals("false")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

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

            if (ZYGOTE_FORK_MODE) {     // ZYGOTE_FORK_MODE = false
                runForkMode();
            } else {
                runSelectLoopMode();	//监听socket
            }

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

主要完成以下的4个工作:

           1) 建立 IPC 通信服务器 ----- registerZygoteSocket

           2)  预加载类和资源:    ------ preloadClasses() / preloadResources()

           3)  启动 system_server  --------- startSystemServer();

           4)  等待 Zygote 被调用 ---------- runSelectLoopMode();


 5, Zygote 孵化器:

           由上述可知: Zygote是一个简单的典型C/S结构,Zygote为提供服务一端,其他进程作为一个客户向服务端申请 “孵化”请求;  Zygote接受到消息后产生一个新的进程。

            在 等待 Zygote 被调用:  runSelectLoopMode()

                                                                   ------ Accept socket connection

                                                                                         -----------  Conntecion.RunOnce()

                                                                                                                     -------------  Read argument

                                                                                                                                             ------  folkAndSpecialize

Zygote.java: 

 native public static int forkAndSpecialize(int uid, int gid, int[] gids,
            int debugFlags, int[][] rlimits);   

   folkAndSpecialize调用的native函数为:dalvik/vm/native/dalvik_system_Zygote.c   

     { "forkAndSpecialize",            "(II[II[[I)I",
                       Dalvik_dalvik_system_Zygote_forkAndSpecialize },


可以看到Activity  利用 Zygote复制 新进程的方式:

 

可以看到子进程继承了父进程的资源。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值