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