
3.2 应用程序进程启动过程介绍
应用程序进程创建过程的步骤比较多,这里分为两个部分来讲解,分别是AMS发送启动应用程序进程请求,以及Zygote接收请求并创建应用程序进程。
3.2.1 AMS发送启动应用程序进程请求
这里先给出AMS发送启动应用程序进程请求过程的时序图,然后对每一个步骤进行详细分析,如图3-1所示。

图3-1 AMS发送启动应用程序进程请求过程的时序图
AMS 如果想要启动应用程序进程,就需要向Zygote进程发送创建应用程序进程的请求,AMS会通过调用startProcessLocked方法向Zygote进程发送请求,如下所示:



在注释1处得到创建应用程序进程的用户ID,在注释2处对用户组ID(gids)进行创建和赋值。在注释3处如果entryPoint为null,则赋值为android.app.ActivityThread,这个值就是应用程序进程主线程的类名。在注释4处调用Process的start方法,将此前得到的应用程序进程用户ID和用户组ID传进去,第一个参数entryPoint我们得知是android.app.ActivityThread,后面章节还会介绍它。接下来查看Process的start方法,如下所示:

在Process的start方法中只调用了ZygoteProcess的start方法,其中ZygoteProcess类用于保持与Zygote进程的通信状态。该start方法如下所示:


ZygoteProcess的start方法调用了startViaZygote方法,如下所示:

在注释1处创建了字符串列表argsForZygote,并将启动应用进程的启动参数保存在argsForZygote中,方法的最后会调用zygoteSendArgsAndGetResult方法,需要注意的是,zygoteSendArgsAndGetResult方法的第一个参数中调用了openZygoteSocketIfNeeded方法①,而第二个参数是保存应用进程的启动参数的argsForZygote。zygoteSendArgsAndGetResult方法如下所示:

zygoteSendArgsAndGetResult 方法的主要作用就是将传入的应用进程的启动参数argsForZygote写入ZygoteState中,ZygoteState是ZygoteProcess的静态内部类,用于表示与Zygote进程通信的状态。结合前面的标注①我们知道ZygoteState其实是由openZygoteSocketIfNeeded方法返回的,那么我们接着来看openZygoteSocketIfNeeded方法做了什么,代码如下所示:

在2.2节讲到Zygote进程启动过程时我们得知,在Zygote的main方法中会创建name为“zygote”的Server端Socket。在注释1处会调用ZygoteState的connect方法与名称为ZYGOTE_SOCKET的Socket建立连接,这里ZYGOTE_SOCKET的值为“zygote”,也就是说,在注释1处与Zygote进程建立Socket连接,并返回ZygoteState类型的primaryZygoteState对象,在注释2处如果primaryZygoteState与启动应用程序进程所需的ABI不匹配,则会在注释3处连接name为“zygote_secondary”的Socket。在2.2.2节中讲到过Zygote的启动脚本有4种,如果采用的是init.zygote32_64.rc或者init.zygote64_32.rc,则name为“zygote”的为主模式,name 为“zygote_secondary”的为辅模式,那么注释2和注释3处的意思简单来说就是,如果连接Zygote主模式返回的ZygoteState与启动应用程序进程所需的ABI不匹配,则连接Zygote辅模式。如果在注释4处连接Zygote辅模式返回的ZygoteState与启动应用程序进程所需的ABI也不匹配,则抛出ZygoteStartFailedEx异常。
3.2.2 Zygote接收请求并创建应用程序进程
Zygote接收请求并创建应用程序进程的时序图如图3-2所示。

图3-2 Zygote接收请求并创建应用程序进程的时序图
Socket连接成功并匹配ABI后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult 方法中讲过,会将应用进程的启动参数argsForZygote写入ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main方法,如下所示:


这些内容在2.2.3节中讲过,但为了更好地理解本节内容,这里再讲一遍。在注释1处通过registerZygoteSocket方法创建了一个Server端的Socket,这个name 为“zygote”的Socket用来等待AMS请求Zygote,以创建新的应用程序进程,关于AMS后面的章节会进行介绍。在注释2处预加载类和资源。在注释3处启动SystemServer进程,这样系统的服务也会由SystemServer进程启动起来。在注释4处调用ZygoteServer的runSelectLoop方法来等待AMS请求创建新的应用程序进程。下面来查看ZygoteServer的runSelectLoop方法:


当有AMS的请求数据到来时,会调用注释2处的代码,结合注释1处的代码,我们得知注释2处的代码其实是调用ZygoteConnection的runOnce方法来处理请求数据的:


在注释1处调用readArgumentList方法来获取应用程序进程的启动参数,并在注释2处将readArgumentList方法返回的字符串数组args封装到Arguments类型的parsedArgs对象中。在注释3处调用Zygote的forkAndSpecialize方法来创建应用程序进程,参数为parsedArgs中存储的应用进程启动参数,返回值为pid。forkAndSpecialize方法主要是通过fork当前进程来创建一个子进程的,如果pid等于0,则说明当前代码逻辑运行在新创建的子进程(应用程序进程)中,这时就会调用handleChildProc方法来处理应用程序进程,如下所示:


handleChildProc方法中调用了ZygoteInit的zygoteInit方法,如下所示:

在注释1处会在新创建的应用程序进程中创建Binder线程池,这将在3.3节详细介绍。在注释2处调用了RuntimeInit的applicationInit方法:


在applicationInit方法中会在注释1处调用invokeStaticMain方法,需要注意的是,第一个参数args.startClass,它指的就是本章开头提到的参数android.app.ActivityThread。接下来我们查看invokeStaticMain方法,如下所示:

可以看到在注释1处通过反射获得了android.app.ActivityThread类,接下来在注释2处获得了ActivityThread的main方法,并将main方法传入注释3处的Zygote中的MethodAndArgsCaller类的构造方法中。在注释3处抛出的MethodAndArgsCaller异常会被Zygote的main方法捕获,至于这里为何采用了抛出异常而不是直接调用ActivityThread的main方法,原理和本书2.3.1节Zygote处理SystemServer进程是一样的,这种抛出异常的处理会清除所有的设置过程需要的堆栈帧,并让ActivityThread的main方法看起来像是应用程序进程的入口方法。下面来查看ZygoteInit.java的main方法是如何捕获MethodAndArgsCaller异常的,如下所示:

当捕获到MethodAndArgsCaller异常时,就会在注释1处调用MethodAndArgsCaller的run方法,MethodAndArgsCaller是Zygote.java的静态内部类:

注释1处的mMethod指的就是ActivityThread的main方法,调用了mMethod的invoke方法后,ActivityThread的main方法就会被动态调用,应用程序进程就进入了ActivityThread的main方法中。讲到这里,应用程序进程就创建完成了并且运行了主线程的管理类ActivityThread。