![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=1739533071-UlF8wl8KlPtVPqMnoRRPAV9mMJk2hNHw-0-1f38f8276c82a83e89dda9493d811770)
图3-1 AMS发送启动应用程序进程请求过程的时序图
AMS 如果想要启动应用程序进程,就需要向Zygote进程发送创建应用程序进程的请求,AMS会通过调用startProcessLocked方法向Zygote进程发送请求,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer788.jpg?sign=1739533071-9M8HdNMNptnXH876vwbed5pRLkWCTOYA-0-127a89c77b09a1745d8019a1e47da822)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer789.jpg?sign=1739533071-ROQmwCXJqlDB4JxV3NeZ2WEerrl7TZql-0-9517e856fb640d6359393fa33e29389e)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer790.jpg?sign=1739533071-j9sLoX6RLCyc6BrVeymcKD93s51BQ8py-0-9bd6de07f59a6be07cd787616d62c369)
在注释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=1739533071-eStTQD6UjTWGh4AGls7gzKeQPUPc3wdQ-0-300eb8b4a451801bc24d6275ef17ad29)
在Process的start方法中只调用了ZygoteProcess的start方法,其中ZygoteProcess类用于保持与Zygote进程的通信状态。该start方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer792.jpg?sign=1739533071-zytmtaKsvCYrtDgWNo2EXKVZW19i08PG-0-8edded9d8a97d39954b1dfb5f1824630)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer793.jpg?sign=1739533071-MKwkmaExzRQk8IV4Gz4G1yze2Woy1EBz-0-be40074d899050ade557e4c599e8a099)
ZygoteProcess的start方法调用了startViaZygote方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer794.jpg?sign=1739533071-rL6oiRSwr6Zo5BOFXIRFx3ZoGzUygDmu-0-582612ffab0da92193148a6a42bf3806)
在注释1处创建了字符串列表argsForZygote,并将启动应用进程的启动参数保存在argsForZygote中,方法的最后会调用zygoteSendArgsAndGetResult方法,需要注意的是,zygoteSendArgsAndGetResult方法的第一个参数中调用了openZygoteSocketIfNeeded方法①,而第二个参数是保存应用进程的启动参数的argsForZygote。zygoteSendArgsAndGetResult方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer795.jpg?sign=1739533071-yIvt3SRn5spVXnwhzFapDQxOq6HCMXy2-0-0c7ddc81082d17d0145070035bfed8cc)
zygoteSendArgsAndGetResult 方法的主要作用就是将传入的应用进程的启动参数argsForZygote写入ZygoteState中,ZygoteState是ZygoteProcess的静态内部类,用于表示与Zygote进程通信的状态。结合前面的标注①我们知道ZygoteState其实是由openZygoteSocketIfNeeded方法返回的,那么我们接着来看openZygoteSocketIfNeeded方法做了什么,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer796.jpg?sign=1739533071-Fqn3sI08dPtExyaQ6JQMaPnhjjjtCf7F-0-c456ff4656b10d1c2dab430090492e1e)
在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=1739533071-sZexSucuQpPEoRdkNmlGn5H1ipKCj7Ba-0-2b92aaafe4737b820365409e927c5fbf)
图3-2 Zygote接收请求并创建应用程序进程的时序图
Socket连接成功并匹配ABI后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult 方法中讲过,会将应用进程的启动参数argsForZygote写入ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer798.jpg?sign=1739533071-at9A7W2NHmYmbB6SyWB21B5kT8olrxcq-0-5fe4301a096d34e8927f11949a0ef64c)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer799.jpg?sign=1739533071-RTxjQNSv7vIPG5wMyyVOACb1bXSvR38Z-0-7804a07273942bfd241c7c783e36cf6a)
这些内容在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=1739533071-3tKKOVmXtGqSHfBZP74ZVBQqMYyVn2tr-0-ebff977381e69afc7fcbda548739397c)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer801.jpg?sign=1739533071-nkWpH2FXMTxPqQy4Af58qtmXKHFtourp-0-e006d85d4e89aa47bf307536e171fc53)
当有AMS的请求数据到来时,会调用注释2处的代码,结合注释1处的代码,我们得知注释2处的代码其实是调用ZygoteConnection的runOnce方法来处理请求数据的:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer802.jpg?sign=1739533071-YtDV6oMfsldUKHrHnhasVHieilaBozio-0-8f6e41994c4e322e23d12a4e09231333)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer803.jpg?sign=1739533071-j25lF2fgdas0cirC94Vbm2lyY7wgKWn8-0-107264689d05b1c5e4292abf9b4eadf4)
在注释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=1739533071-qlNUYcsLLdLz1zFVBllQhIBdeH3KoEz4-0-b7167cb68eb121403693c49e4d604078)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer805.jpg?sign=1739533071-pqlMDoM9yAbmhdVtO8QzjGygtkmLrBqa-0-3f3191fe9b4eb12cc4a9ef03914774e0)
handleChildProc方法中调用了ZygoteInit的zygoteInit方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer806.jpg?sign=1739533071-acA7uyyUKFm0mH6Fq4CvHdxWnpDr4V5z-0-5621cc93868ef9d5fffaed529a0e4053)
在注释1处会在新创建的应用程序进程中创建Binder线程池,这将在3.3节详细介绍。在注释2处调用了RuntimeInit的applicationInit方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer807.jpg?sign=1739533071-ClJhxXzTSTl7cJioqAFfcNqM6mtLBKUO-0-ac5d9464cbc8bd259a31f536ee11e5c7)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer808.jpg?sign=1739533071-Fd0cZabzGmZeirtQZoP2CVpZOF4dxHDm-0-163292876ca988997b2e4da47e1d2ef6)
在applicationInit方法中会在注释1处调用invokeStaticMain方法,需要注意的是,第一个参数args.startClass,它指的就是本章开头提到的参数android.app.ActivityThread。接下来我们查看invokeStaticMain方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer809.jpg?sign=1739533071-F3gYfxHzNH0XujmJLcPSa40YsBoL6R0M-0-27529256cb580f977c40d1d0b24bb9c6)
可以看到在注释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=1739533071-2ImEcoyDEzudhlwJ1SwePAStVeJjBvsR-0-6d30bbbe9df16f3fdca33ed8eced3069)
当捕获到MethodAndArgsCaller异常时,就会在注释1处调用MethodAndArgsCaller的run方法,MethodAndArgsCaller是Zygote.java的静态内部类:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer811.jpg?sign=1739533071-WR9yxsXiM0aNIzkjkFjW19wBeacrQiyd-0-eec5c856c858d0ac47d2cf79f9aa45a3)
注释1处的mMethod指的就是ActivityThread的main方法,调用了mMethod的invoke方法后,ActivityThread的main方法就会被动态调用,应用程序进程就进入了ActivityThread的main方法中。讲到这里,应用程序进程就创建完成了并且运行了主线程的管理类ActivityThread。