App启动流程:总体说明

作者: sjandroid | 来源:发表于2019-04-17 14:40 被阅读24次

概述:

“应用程序启动过程”其实说的就是“冷启动”过程。

App启动流程总体是由以下3部分组成

  • 为目标App启动做准备
  • 启动App进程
  • App进程内部操作

为目标App启动做准备(详细请戳 <<为目标App启动做准备>>)

这部分内容概括来说主要就是2件事:

  • “Launcher进程把待启动App的信息封装到Intent中,然后通过Binder把该信息发送给system_server进程中的AMS服务。
  • 然后AMS拿这些信息为启动App做一些前期的准备工作”。

这些工作内容细分如下:

  • 通过PMS.resolveIntent()根据提供的待启动Activity的Intent信息,从已安装的应用中解析出与该Activity相对应的ActivityInfo。
  • 检查传递来的参数,如果参数不正确,将会返回相应的err信息,用于提醒用户出现了什么错误。
    1. 如果,Intent获取的要启动的Activity组件的"ComponentName"信息为null的话(未通过Intent指定要跳转的Activity的确切的类名信息),则不会继续后续操作,并会返回此err。
    2. 如果,通过PMS找不到待启动Activity的详细信息(ActivityInfo),则不会继续后续操作,并会返回此err。
  • 与Activity栈相关操作
    1. 为待启动Activity组件新创建一个ActivityRecord。
    2. 缓存待启动ActivityRecord、调用者的ActivityRecord、Intent等信息。
    3. 初始化代启动Activity的lauchMode与launchFlags。
    4. 为代启动ActivityRcord创建或者选取一个可用的TaskRecord(因为启动的其它app的根Activity,所以会为该Activity创建一个新的TaskRecord)。
    5. 添加待启动ActivityRecord至“前台栈”的栈顶。
    6. 显示theme中设置的预览窗口。
    7. “暂停所有ActivityStack中处于RESUMED状态的Activity”,此时Launcher这个Activity也会被 Pause 掉。
    8. 激活“前台栈”中处于栈顶位置的待启动Activity。

启动App进程(详细请戳 <<启动App进程>>)

启动应用程序的进程主要分2个方面:

  • AMS向Zygote发起fork子进程的过程

    • AMS调用其内部的“startProcessLocked()”来开启启动app进程的入口。该方法主要做的是:组装发给zygote进城的用于启动子进程的参数列表(这些参数包括:uid,gid,entryPoint 参数等,entryPoint参数的值为ActivityThread的类全限定名。该参数用于fork子进程之后启动每个app进程的ActivityThread去做初始化操作。)
    • 通过层层调用最终会执行 ZygoteProcess.startViaZygote()
      1:首先,该方法首先会把AMS服务传过来的参数封装到一个argsForZygote参数列表中。
      2:其次,调用ZygoteProcess内部的openZygoteSocketIfNeeded()与Zygote进程建立Socket连接。
      3:最后,调用ZygoteProcess的zygoteSendArgsAndGetResult(),该方法主要做的事情是:将请求参数列表发送到zygote进程,并接收Zygote进程启动子进程的响应结果。
  • Zygote接收AMS的请求创建子进程过程

    • Zygote进程被init进程拉起后,会通过反射调用ZygotInit的main(),该方法主要做的事情是:
      1:初始化ZygoteServer并创建服务端Socket用于接收、执行其它进程向Zygote进程发起的请求
      2:启动SystemServer进程
      3:最后调用runSelectLoop()开始循环接收其它进程发起的请求
    • 如果检测到有请求发过来,runSlectLoop()中会把一次Socket封装成ZygoteConnection,而后执行其runOnce()方法。
    • 在runOnce()内部会调用Zygote.forkAndSpecialize():内部调用native方法进行实际的fork子进程操作。fork成功的话则子进程pid等于0,不为0则表示fork失败(fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次。)。
    • 如果pid为0,则表示当前代码执行在子进程,需要执行handleChildProc(),该方法主要做的是:
      1:关闭与Zygote进程的Socket连接。
      2:执行ZygoteInit.zygoteInit()。
      ZygoteInit.zygoteInit(),该方法主要执行"子进程"的运行时初始化操作(这些初始化包括:启动Binder线程池、创建VM、以及反射执行子进程ActivityThread线程等)。

App进程内部操作(详细请戳 <<App进程内部操作>>)

执行ActivityThread.attach(),进行“连接”操作。其中主要包括:

  • AMS.attachApplication():此时所在进程是fork之后的子进程。通过ActivityService.getService()获取AMS服务在本地进程的代理对象,然后通过Binder调用AMS的attachApplication()。

  • AMS.attachApplicationLocked():
    1:其内部会先调用ApplicationThread.bindApplication()初始化App进程的Application。具体的会向ActivityThread的Handler中发送一个BIND_APPLICATION消息。Handler在接收到发送的“BIND_APPLICATION消息”后去执行ActivityThread.handleBindApplication()。

    • ContextImpl.createAppContext():创建ContextImpl实例
    • 反射初始化Instrumentation实例,并赋值给 mInstrumentation。执行Instrumentation.init()进行初始化操作。
    • LoadApk.makeApplication():反射Application,并执行Application的attach(),onCreate()方法。

    2:等启动完App的Applicaiton后,AMS会调用ASS.attachApplicationLocked()通过App的ApplicationThread通知app初始化根Activity。具体操作如下:
    1:首先,调用ASS.attachApplicationLocked()。其内部会找到处于“前台栈”栈顶的待启动Activity。
    2:最后,调用ASS.realStartActivityLocked()通过Binder来通知App进程初始化待启动也就是App注册的根Activity。

相关文章

网友评论

    本文标题:App启动流程:总体说明

    本文链接:https://www.haomeiwen.com/subject/opvbwqtx.html