Zygote的父进程是init进程,他孵化了SystemServer进程,以及咱们的运用进程。

一、Zygote作用

功能首要是

:发动安卓虚拟机DVM

:发动SystemServer(Android体系进程)

:孵化运用进程

:加载 常用类 JNI函数 主题资源 共享库 等

Zygote进程和体系其他进程的关系如图所示:

认识Zygote

二、Zygote进程发动和运用进程发动

如图所示:

认识Zygote

1.Zygote进程发动流程

Zygote是由init进程发动的,init进程是Linux体系发动后用户空间的第一个进程, 首要会去加载init.rc配置文件,然后发动其间界说的体系服务(Zygote,ServiceManager等), Init进程创立Zygote时,会调用app_main.cpp的main() 办法, 发动Zygote后,发动安卓虚拟机,接着在native层中经过jni调用java层的ZygoteInit的main()。

<!--app_main.cpp
int main(int argc, char* const argv[])
{
    //  创立Android运行时目标
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // 代码省略...
    // 调用AppRuntime.start办法,
    // 而AppRuntime是AndroidRuntime的子类,并且没有重写start办法
    // 因此调用的是AndroidRuntime的start办法
    runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
-->

这里总共就做了两件事,第一件创立AppRuntime,第二件调用start办法,具体看一下start办法:

<!--
/*
 * AndroidRuntime.cpp
 * Start the Android runtime. 
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    /* start the virtual machine */
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
-->

startVM — 发动Java虚拟机

startReg — 注册JNI 经过JNI调用Java办法,履行com.android.internal.os.ZygoteInit 的 main 办法。

ZygoteInit .main首要干了4个事情,如下:

<!--
 /*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
 public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
        ...
        try {
            ...
            // 1.preload提前加载框架通用类和体系资源到进程,加快进程发动
            preload(bootTimingsTraceLog);
            ...
            // 2.创立zygote进程的socket server服务端目标
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            ...
	    // 3.发动SystemServer(Android体系进程)
	    forkSystemServer
	    ...
            // 4.进入死循环,等候AMS发恳求过来
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            ...
        } finally {
            ...
        }
        ...
	caller.run();//履行MethodAndArgsCaller包装后的runnable
    }
-->

1.创立了ZygoteServer:这是一个Socket相关的服务,目的是进行跨进程通信。

2.预加载preload:预加载相关的资源。

3.创立SystemServer进程: 经过forkSystemServer割裂出了两个进程,一个Zygote进程,一个SystemServer进程。而且由于是割裂的, 所以新割裂出来的进程也具有虚拟机,也能调用JNI,也具有预加载的资源,也会履行后续的代码。

4.履行runSelectLoop():内部是一个while(true)循环,等候AMS创立新的进程的請求音讯。(想想Looper.loop())

2.Zygote发动运用进程流程

zygote进程经过Socket监听接纳AMS的恳求,fork创立子运用进程,然后pid为0时进入子进程空间,然后在ZygoteInit#zygoteInit中完结进程的初始化动作。

先看一下ZygoteServer.runSelectLoop

<!--
 /*frameworks/base/core/java/com/android/internal/os/ZygoteServer.java*/
 Runnable runSelectLoop(String abiList) {
     // 进入死循环监听
     while (true) {
        while (--pollIndex >= 0) {
           if (pollIndex == 0) {
             ...
           } else if (pollIndex < usapPoolEventFDIndex) {
             // Session socket accepted from the Zygote server socket
             // 得到一个恳求连接封装目标ZygoteConnection
             ZygoteConnection connection = peers.get(pollIndex);
             // processCommand函数中处理AMS客户端恳求
             final Runnable command = connection.processCommand(this, multipleForksOK);
             ...
           }
        }
     }
 }
 -->

再通過ZygoteConnection中处理AMS创立新运用进程的恳求。

 <!--
 //ZygoteConnection.java
 Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
         ...
         // 1.fork创立运用子进程
         pid = Zygote.forkAndSpecialize(...);
         try {
             if (pid == 0) {
                 ...
                 // 2.pid为0,当时处于新创立的子运用进程中,处理恳求参数
                 return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
             } else {
                 ...
                 handleParentProc(pid, serverPipeFd);
             }
          } finally {
             ...
          }
 }
  private Runnable handleChildProc(ZygoteArguments parsedArgs,
            FileDescriptor pipeFd, boolean isZygote) {
        ...
        // 关闭从父进程zygote承继过来的ZygoteServer服务端地址
        closeSocket();
        ...
        if (parsedArgs.mInvokeWith != null) {
           ...
        } else {
            if (!isZygote) {
                // 持续进入ZygoteInit#zygoteInit持续完结子运用进程的相关初始化工作
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mDisabledCompatChanges,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                ...
            }
        }
    }
-->

经过调用Zygote.forkAndSpecialize()函数来创立子进程,会有一个回来值pid,分别在子进程和父进程各回来一次, 子进程回来 0 ,父进程回来1,经过判别pid为0仍是1来判别当时是是父进程仍是子进程;默许子进程承继父进程是承继了父进程的一切资源 分叉后的进程会将socket停掉并重新初始化一些数据,但preload的资源和类保和VM留了下来,运用进程承继了Zygote进程所创立的虚拟机, 运用进程的在运用的时分就不需要再去创立,自此新的进程和zygote进程分道扬镳。

留意:其间包含运用进程的主线程也是在这里从zygote进程承继而来的,运用进程的主线程并不是自己自动创立的新线程。

Zygote发动运用进程的时分不管父进程中有多少个线程,子进程在创立的时分都只有一个线程,对于子进程来说,多出现的线程在子进程中都不复存在, 因为如果其他线程也被复制到子进程,这时在子进程中就会存在一些问题,有时程序在履行的过程中可能会形成死锁,状态不一致等,所以比较安全的做法是在创立子进程的时分,只保存父进程的 主线程,其他都在暂停(此时线程资源是开释的所以不会承继到子进程),子进程发动完后再重启这些线程。

ZygoteInit.zygoteInit办法完结运用进程初始化:

<!--
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        ...
        // 原生增加名为“ZygoteInit ”的systrace tag以标识进程初始化流程
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();
        // 1.RuntimeInit#commonInit中设置运用进程默许的java反常处理机制
        RuntimeInit.commonInit();
        // 2.ZygoteInit#nativeZygoteInit函数中JNI调用发动进程的binder线程池
        ZygoteInit.nativeZygoteInit();
        // 3.RuntimeInit#applicationInit中反射创立ActivityThread目标并调用其“main”进口办法
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
 }
-->

1.设置运用进程默许的java反常处理机制(可以实现监听、拦截运用进程所有的Java crash的逻辑);

2.JNI调用发动进程的binder线程池(留意运用进程的binder线程池资源是自己创立的并非从zygote父进程承继的);

3.经过反射创立ActivityThread目标并调用其“main”进口办法。

最后再看看RuntimeInit.applicationInit做了啥:

<!--
 /*frameworks/base/core/java/com/android/internal/os/RuntimeInit.java*/
 protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        ...
        // 结束“ZygoteInit ”的systrace tag
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
  }
  protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;
        try {
            // 1.反射加载创立ActivityThread类目标
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            ...
        }
        Method m;
        try {
            // 2.反射调用其main办法
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            ...
        } catch (SecurityException ex) {
            ...
        }
        ...
        // 3.触发履行以上逻辑
        return new MethodAndArgsCaller(m, argv);
    }
-->

首要就是调用ActivityThread.main办法,从此进入ActivityThread中。

三、参考资料

【Zygote进程的发动 –学习笔记】 blog.csdn.net/qq\_4223721…

【说说你对zygote的了解?】www.cnblogs.com/rxh1050/p/1…

【Zygote Fork机制与资源预加载】www.jianshu.com/p/be384613c…