![Android进阶解密](https://wfqqreader-1252317822.image.myqcloud.com/cover/331/31186331/b_31186331.jpg)
3.2 应用程序进程启动过程介绍
应用程序进程创建过程的步骤比较多,这里分为两个部分来讲解,分别是AMS发送启动应用程序进程请求,以及Zygote接收请求并创建应用程序进程。
3.2.1 AMS发送启动应用程序进程请求
这里先给出AMS发送启动应用程序进程请求过程的时序图,然后对每一个步骤进行详细分析,如图3-1所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer787.jpg?sign=1739500085-tSkhtV8CiorAianGWPXvdrIBgpxGzt1U-0-7b5ed9407800d480a1817465cf750bb2)
图3-1 AMS发送启动应用程序进程请求过程的时序图
AMS 如果想要启动应用程序进程,就需要向Zygote进程发送创建应用程序进程的请求,AMS会通过调用startProcessLocked方法向Zygote进程发送请求,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer788.jpg?sign=1739500085-9JbfEodwnH97HoYjpqcfk8RlKEno4bqM-0-927460d4f132934402708f2756afc1b8)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer789.jpg?sign=1739500085-n5JVl4OiIPCWVj4YXw1MobWJOl88BJfF-0-d584d66c301dffa93ab757e8ea928e7e)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer790.jpg?sign=1739500085-svBZnWwZ91P13lrXGACyDyYJFBiVBLG8-0-5723f0904f64af89ba14e391aaa40ef1)
在注释1处得到创建应用程序进程的用户ID,在注释2处对用户组ID(gids)进行创建和赋值。在注释3处如果entryPoint为null,则赋值为android.app.ActivityThread,这个值就是应用程序进程主线程的类名。在注释4处调用Process的start方法,将此前得到的应用程序进程用户ID和用户组ID传进去,第一个参数entryPoint我们得知是android.app.ActivityThread,后面章节还会介绍它。接下来查看Process的start方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer791.jpg?sign=1739500085-9iVVoj3306CEsduAnAaseT6GO5QqubIg-0-bdd3a6cd6748bc4a76dfb6d4a422ecfb)
在Process的start方法中只调用了ZygoteProcess的start方法,其中ZygoteProcess类用于保持与Zygote进程的通信状态。该start方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer792.jpg?sign=1739500085-HfF9tJftIHDhOE0MwpbVS6SnH0PieypS-0-da2743014effdb342e42447cb056d0b1)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer793.jpg?sign=1739500085-BiepxC6CoDGZELtBWSQInDaMhFwvlKBq-0-0172b13ad8dd6436dc10d3e2611c1ac3)
ZygoteProcess的start方法调用了startViaZygote方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer794.jpg?sign=1739500085-LYYDEt5efAnMbni2E3MDcGMj1w9X6eXH-0-beca8113ea3f3c536a477efde8533106)
在注释1处创建了字符串列表argsForZygote,并将启动应用进程的启动参数保存在argsForZygote中,方法的最后会调用zygoteSendArgsAndGetResult方法,需要注意的是,zygoteSendArgsAndGetResult方法的第一个参数中调用了openZygoteSocketIfNeeded方法①,而第二个参数是保存应用进程的启动参数的argsForZygote。zygoteSendArgsAndGetResult方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer795.jpg?sign=1739500085-b2JTLuyrLuwck95SF1DCCJ07Zh30EGbM-0-b71f3abd914c4da06661dcbceb0415fc)
zygoteSendArgsAndGetResult 方法的主要作用就是将传入的应用进程的启动参数argsForZygote写入ZygoteState中,ZygoteState是ZygoteProcess的静态内部类,用于表示与Zygote进程通信的状态。结合前面的标注①我们知道ZygoteState其实是由openZygoteSocketIfNeeded方法返回的,那么我们接着来看openZygoteSocketIfNeeded方法做了什么,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer796.jpg?sign=1739500085-w0cLG7PINC18CFHiNYVYvtuSNKbWQhjy-0-d5203496037a1a83f02df75d37d7a064)
在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所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer797.jpg?sign=1739500085-RDyS1gba6sRF7eVa2l2N5Ihtb4A3C1Rp-0-18673ba1e29895b35da27e7d596f9d36)
图3-2 Zygote接收请求并创建应用程序进程的时序图
Socket连接成功并匹配ABI后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult 方法中讲过,会将应用进程的启动参数argsForZygote写入ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer798.jpg?sign=1739500085-QDqUcg1jQAmAFCWTDmJoViYBgVqAsGGl-0-4767580067bd1bd29885b4a3528b2d1f)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer799.jpg?sign=1739500085-PuHmDfjK7TLebnbuXoSXY6Qh5KjazzEb-0-22139cff2d25f749b6ef33df65bb995b)
这些内容在2.2.3节中讲过,但为了更好地理解本节内容,这里再讲一遍。在注释1处通过registerZygoteSocket方法创建了一个Server端的Socket,这个name 为“zygote”的Socket用来等待AMS请求Zygote,以创建新的应用程序进程,关于AMS后面的章节会进行介绍。在注释2处预加载类和资源。在注释3处启动SystemServer进程,这样系统的服务也会由SystemServer进程启动起来。在注释4处调用ZygoteServer的runSelectLoop方法来等待AMS请求创建新的应用程序进程。下面来查看ZygoteServer的runSelectLoop方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer800.jpg?sign=1739500085-TEDiebUwFbQWIijeKXzyf7FZjQHWbqek-0-b9d3d10513045b314d475ba059395374)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer801.jpg?sign=1739500085-g2IHKcpw1Vi2e4gfRljLZC4r5bbmuigc-0-91d1a995e401fe0134ef06fc4f1dcf2c)
当有AMS的请求数据到来时,会调用注释2处的代码,结合注释1处的代码,我们得知注释2处的代码其实是调用ZygoteConnection的runOnce方法来处理请求数据的:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer802.jpg?sign=1739500085-I3GT2F5QEUfdhdyWlCcw1CwbeVaJKF9P-0-956bad5ac88c40336d15e749baf8c3ad)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer803.jpg?sign=1739500085-IlBVsWKXPVMufvKbRN0PFwuby6SUD5lt-0-b68fe22f6b576d82525bef48a81fca57)
在注释1处调用readArgumentList方法来获取应用程序进程的启动参数,并在注释2处将readArgumentList方法返回的字符串数组args封装到Arguments类型的parsedArgs对象中。在注释3处调用Zygote的forkAndSpecialize方法来创建应用程序进程,参数为parsedArgs中存储的应用进程启动参数,返回值为pid。forkAndSpecialize方法主要是通过fork当前进程来创建一个子进程的,如果pid等于0,则说明当前代码逻辑运行在新创建的子进程(应用程序进程)中,这时就会调用handleChildProc方法来处理应用程序进程,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer804.jpg?sign=1739500085-ylUKkcGHmAQnMQQCKYqmha4ZoYSp6DWI-0-b3685f2dcb7ff77da72fab63ae8b2aa4)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer805.jpg?sign=1739500085-VEuwWLS1ZYpxwErK5ZYgSxO9JkM7EHFE-0-3900452f3536ae3df8de7ef3da853873)
handleChildProc方法中调用了ZygoteInit的zygoteInit方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer806.jpg?sign=1739500085-4DtLHCBuKpp0hBNK4LIcMNA3p0WvZbVN-0-9063b4ac3ea5cd88ca5baf115e0519c6)
在注释1处会在新创建的应用程序进程中创建Binder线程池,这将在3.3节详细介绍。在注释2处调用了RuntimeInit的applicationInit方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer807.jpg?sign=1739500085-szVaUKZn1vNjIWsAO9KJmG6S2saMrVcx-0-a7d82724999c96a4cbaf909417645811)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer808.jpg?sign=1739500085-x0tbW8qA96KIpncIY9tAY2pPSMgKXqzh-0-56ceb5ac1fac8faf786907f77691d648)
在applicationInit方法中会在注释1处调用invokeStaticMain方法,需要注意的是,第一个参数args.startClass,它指的就是本章开头提到的参数android.app.ActivityThread。接下来我们查看invokeStaticMain方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer809.jpg?sign=1739500085-A6bnPwEPTd3PtG9cUKllSnMPRNBtkDPA-0-7a6cb6340bee7978317d4e8040a43743)
可以看到在注释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异常的,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer810.jpg?sign=1739500085-crr4J9pmvdq5JuMuwenj84bAZmNNfNR3-0-1c3270f342ab5f9fd03e1bb1f2452779)
当捕获到MethodAndArgsCaller异常时,就会在注释1处调用MethodAndArgsCaller的run方法,MethodAndArgsCaller是Zygote.java的静态内部类:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer811.jpg?sign=1739500085-GD1zojRHsn49G9a5lwlsYB6MLK0Z8e0u-0-6acf79495d451492dc8ce8b7d431a107)
注释1处的mMethod指的就是ActivityThread的main方法,调用了mMethod的invoke方法后,ActivityThread的main方法就会被动态调用,应用程序进程就进入了ActivityThread的main方法中。讲到这里,应用程序进程就创建完成了并且运行了主线程的管理类ActivityThread。