App启动流程分析

简介

  • 1.点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
  • 2.system_server进程接收到请求后,向zygote进程发送创建进程的请求;
  • 3.Zygote进程fork出新的子进程,即App进程;
  • 4.App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  • 5.system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
  • 6.App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
  • 7.主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
  • 8.到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

概念

zygote

在Android系统里面,zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。

我们都知道,每一个APP其实都是一个单独的dalvik虚拟机,一个单独的进程,所以当系统里面的第一个zygote进程运行之后,如果在启动APP,为了实现资源共用和更快的速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的。

system_server

也是一个进程,而且是由zygote进程fork出来的。这个进程非常的重要,因为系统里面的重要的服务都是在这个进程里面开启的,比如
AMS、PMS、WMS等等。

ActivityManagerService

简称AMS,服务端对象,负责系统中所有Activity的生命周期。ActivityManagerService是在system_server进程开启的时候,就会初始化的。

Android系统的服务端和客户端

服务端指的是所有APP共用的系统服务,比如AMS、PMS、WMS。当你需要打开一个APP时,需要包名MainActivity的类名就可以打开了。这个打开的过程就是服务端提供的。

服务端的设计涉及到三个进程的通信,zygote、system_server和app进程。其中app进程与AMS通过Binder进行IPC通信。AMS与zygote是通过socket进行IPC通信。

在Android系统中,任何一个Activity的启动都是由AMS和应用程序进程(主要是ActivityThread)相互配合来完成的。AMS服务统一调度系统中所有进程的Activity启动,而每个Activity的启动过程则由其所属的进程具体来完成。

Launcher

本质就是一个APP

1
2
3
4
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener {
}

Instrumentation和ActivityThread

每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。这个类就是完成对Application和Activity初始化和生命周期的工具类。

ActivityThread,依赖于UI线程。App和AMS是通过Binder传递信息的,那么ActivityThread就是专门与AMS的外交工作的。

ApplicationThread

App的启动以及Activity的显示都需要AMS的控制,那么我们便需要和服务端的沟通,而这个沟通是双向的。

客户端–>服务端

而且由于继承了同样的公共接口类,ActivityManagerProxy提供了与ActivityManagerService一样的函数原型,使用户感觉不出Server是运行在本地还是远端,从而可以更加方便的调用这些重要的系统服务。

服务端–>客户端

还是通过Binder通信,不过是换了另外一对,换成了ApplicationThread和ApplicationThreadProxy。
他们也都实现了相同的接口IApplicationThread

1
2
3
4
5
private class ApplicationThread extends ApplicationThreadNative {}

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}

class ApplicationThreadProxy implements IApplicationThread {}

流程分析

创建进程

  1. 先从Launcher的startActivity()方法,通过Binder通信,调用ActivityManagerService的startActivity方法。
  2. 一系列折腾,最后调用startProcessLocked()方法来创建新的进程。
  3. 该方法会通过前面讲到的socket通道传递参数给Zygote进程。Zygote孵化自身。调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid。
  4. 调用ActivityThread.main()方法,ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环。

更简化的流程为:

  1. App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,则发送进程便是该App所在进程。发起进程先通过binder发送消息给system_server进程;
  2. system_server进程:调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求;
  3. zygote进程:在执行ZygoteInit.main()后便进入runSelectLoop()循环体内,当有客户端连接时便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程;
  4. 新进程:执行handleChildProc方法,最后调用ActivityThread.main()方法。

绑定Application

上面创建进程后,执行ActivityThread.main()方法,随后调用attach()方法。

将进程和指定的Application绑定起来。这个是通过上节的ActivityThread对象中调用bindApplication()方法完成的。该方法发送一个BIND_APPLICATION的消息到消息队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用makeApplication()方法来加载App的classes到内存中。

方法调用流程图如下:

更简化的流程为:

显示Activity界面

经过前两个步骤之后, 系统已经拥有了该application的进程。 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了。

实际调用方法是realStartActivity(), 它会调用application线程对象中的scheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 通过 handleLaunchActivity()来处理该消息。在 handleLaunchActivity()通过performLaunchActiivty()方法回调Activity的onCreate()方法和onStart()方法,然后通过handleResumeActivity()方法,回调Activity的onResume()方法,最终显示Activity界面。

更简化的流程为:

Binder通信


ATP: ApplicationThreadProxy
AT: ApplicationThread
AMP: ActivityManagerProxy
AMS: ActivityManagerService

  1. system_server进程中调用startProcessLocked方法,该方法最终通过socket方式,将需要创建新进程的消息告知Zygote进程,并阻塞等待Socket返回新创建进程的pid;
  2. Zygote进程接收到system_server发送过来的消息, 则通过fork的方法,将zygote自身进程复制生成新的进程,并将ActivityThread相关的资源加载到新进程app process,这个进程可能是用于承载activity等组件
  3. 在新进程app process向servicemanager查询system_server进程中binder服务端AMS, 获取相对应的Client端,也就是AMP. 有了这一对binder c/s对, 那么app process便可以通过binder向跨进程system_server发送请求,即attachApplication()
  4. system_server进程接收到相应binder操作后,经过多次调用,利用ATP向app process发送binder请求, 即bindApplication. system_server拥有ATP/AMS, 每一个新创建的进程都会有一个相应的AT/AMP,从而可以跨进程 进行相互通信. 这便是进程创建过程的完整生态链
您的支持是我原创的动力