type
status
date
slug
summary
tags
category
icon
password
之前也写过Application启动流程之类的文章,但是总感觉这个程度不够,再来总结下.
先把脑子里那一堆忘掉,想一想要启动一个Application需要干什么:
  • 需要知道app可执行文件的位置
    • 即apk中的dex文件,或者经过dexopt优化过后的dex文件,在APK安装的时候信息已经被记录在了手机上.
  • 创建app进程
    • Android是基于Linux的,创建进程的方式一般有两种,fork和exec,在Android中应用进程都是从zygote进程fork的.
  • 进程创建了得执行一个main()入口方法,把应用跑起来
    • main()入口在ActivityThread
  • Android还比较特殊,需要启动一个主界面,即Launch Activity
    • APK安装时已经把Activity的各种信息保存了,因此找到对应APP的Launch Activity即可
再把流程走一遍吧!

点击桌面上的App Icon

Launcher 应用中 点击APP Icon之后会调用:
Launcher中有:
最终还是会调用到startActivity()

Activity#startActivity()

这里的mMainThread即是ActivityThread,不过不是目标应用的ActivityThread.
后面依次经历如下类的调用:
  1. Instrumentation#execStartActivity()
  1. ActivityTaskManagerService#startActivityAsUser()
  1. ActivityStartController#obtainStarter()
  1. ActivityStarter#startActivity() -> ActivityStarter#startActivityUnchecked()
  1. RootActivityContainer#resumeFocusedStacksTopActivities()
  1. ActivityStack#resumeTopActivityUncheckedLocked() -> ActivityStack#resumeTopActivityInnerLocked()
  1. ActivityStackSupervisor#startSpecificActivityLocked()
  1. 目标app如果有线程正在运行,则ActivityStackSupervisor#realStartActivityLocked()
  1. 目标app如果没有线程在运行,则会发送一个Handler Message,调用ActivityManagerInternal#startProcess()

启动app进程

ActivityManagerInternal#startProcess()方法开始看:
ActivityManagerService中有一个内部类LocalService就是继承的ActivityManagerInternal,因此看一下startProcess的实现方法:
ProcessList中看下:
这里默认是异步的方式启动进程,即在一个单独的线程中启动进程:
其实这个方法里有一个判断,即regular_zygote,app_zygote,webview_zygote.其实这三个判断,在HostingRecord中可以简单的看出来区别:
  • regular_zygote,一般是各种Activity的启动时候用的
  • app_zygote,一般是各种Service启动的时候用的
  • webview_zygote,当然是webview用的
后面就进入了Process中了:
这里的USAP就是unspecialized app process 的意思.
这里分两步:
  1. 打开zygote 的socket 连接
    1. 对于Android而言,这里首先会尝试打开64位的zygote socket,如果失败才会尝试32位的zygote.然后返回一个连接状态ZygoteState.
      不管是64位还是32位的zygote socket,过程都是一样的:
      具体的连接过程看下面:
      到这里已经建立起了和zygote的local socket连接.
  1. 通过建立的local socket 连接发送命令并且返回结果
    1. 这里发送的命令都在前面组装的argsForZygote中,在这里其实就是使用zygote 启动(fork) 指定的进程的命令.
经历了这些步骤之后,app 进程也就创建成功了,再来看下zygote具体是如何响应fork请求的.

Zygote fork app进程

ZygoteServer和ZygoteConnection中会收到socket请求,并做对应的处理:
到Zygote中看看:
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp中看看:
进程fork之后,会执行下面的逻辑(ZygoteConnection.java中):
再来看一下ZygoteInit:
这个方法里干了很多重要的事情:
  • 设置异常处理的逻辑和一些崩溃日志的输出逻辑
    • 具体的异常捕获话题就不在这里写了,偏题了.
  • 找到ActivityThread的入口方法,并反射调用
    • 到这里ActivityThread.main()就被成功执行了.
      那么实际上这个返回的Runnable是谁运行的,在什么线程里运行的呢?
      答案是在ZygoteServerrunSelectLoop方法中会再处理一下,最后交由ZygoteInit去执行.

ActivityThread.main()

最为关键的调用就是attach方法:
然后会调用到ApplicationThread中的bindApplication()方法:
这里会发送一个BIND_APPLICATION消息,Handler接收到之后会进行处理:
这个过程中做了很多事,但是主要就以下这些:
  • 告诉ART虚拟机一些信息,比如应用的包名,数据目录等
  • 各种调试功能,Profile功能判断与设置
  • 告诉虚拟机当前UI线程是敏感线程
  • 硬件加速的支持
  • 创建LoadedApk对象
  • 创建Context对象
  • 在创建Application之前,创建Instrumentation,用于监视app与系统的交互
  • 创建Application对象
  • 安装ContentProvider
  • 利用Instrumentation执行Application#onCreate()回调

Application对象的创建

上面已经说过,会调用LoadedAPk#makeApplication()方法去创建Application对象:
可以看到其实还是调用的Instrumentation去创建Application对象:
最后会进入到AppComponentFactory中利用ClassLoader去创建Application对象:
到这里Application对象就创建成功了,并且调用了Application的attach(context)方法.
attach方法子类是不可以重写的,但是attachBaseContext可以,这里可以看到Application还持有了LoadedApk对象.

Application#onCreate()执行

在application对象attach(context)之后,Instrumentation会中会调用Application#onCreate()方法:
其实在调用Application#onCreate()之前,可以在Instrumentation中插入一些钩子逻辑,这个在前面的代码中可以看到端倪:
InstrumentationonCreate()是一个空方法,可以实现自己的Instrumentation以插入一些逻辑,以在应用代码执行前做一些特殊的处理.
到这里Application就已经创建完成,并且执行了onCreate了.剩下的就是其中Launcher Activity的流程了,这篇文章源码流程已经够多了,后面单独写一篇文章梳理下Activity的启动流程吧!

总结

  • Application其实也是通过ClassLoader加载的
  • zygote fork出了进程,但是并不代表执行了ActivityThread的main方法
  • zygote是java世界的进程,fork出 app进程之后,app进程也拥有一份拷贝数据
  • Instrumentation和LoadedApk在Application的启动过程中很重要,可以利用它做很多事情
  • 全局的异常捕获与处理也是在这个阶段设置的
  • 堆内存的使用上限也是这个过程设置的
  • Context的创建,主线程Looper等都是在这个过程中进行的
  • Debug模式,Profile模式的逻辑判断也是在这个过程进行的
  • zygote的通信机制:local socket + file descriptor
GC与ReferenceAPK安装流程分析-普通APP的安装
Loading...