为了便于阅读, 应邀将Android App性能优化系列, 转移到掘金原创上来.
掘金的新出的"收藏集"功能能够用来作系列文集了.html
这是一篇关于Android Application启动流程分析的译文, 为咱们后面讲App启动优化打个基础.android
译者注:
原文分红两个部分, 连接以下:
multi-core-dump.blogspot.com/2010/04/and…
multi-core-dump.blogspot.com/2010/04/and…
章节标题由译者加注.浏览器
做者曾经在高通的Android性能组工做, 主要工做是优化Android Application的启动时间.性能优化
要想优化App启动时间, 第一步就是了解App启动进程的工做原理. 有几个基础理论:app
Android Application与其余移动平台有两个重大不一样点:socket
Android Application组件包括:ide
Android进程与Linux进程同样. 默认状况下, 每一个apk运行在本身的Linux进程中. 另外, 默认一个进程里面只有一个线程---主线程. 这个主线程中有一个Looper实例, 经过调用Looper.loop()从Message队列里面取出Message来作相应的处理.oop
那么, 这个进程什么时候启动的呢?
简单的说, 进程在其须要的时候被启动. 任意时候, 当用户或者其余组件调取你的apk中的任意组件时, 若是你的apk没有运行, 系统会为其建立一个新的进程并启动. 一般, 这个进程会持续运行直到被系统杀死. 关键是: 进程是在被须要的时候才建立的.性能
举个例子, 若是你点击email中的超连接, 会在浏览器里面打开一个网页. Email App和浏览器App是两个不一样的App, 运行在不一样的进程中. 此次点击事件促使Android系统去建立了一个新的进程来实例化浏览器的组件.优化
首先, 让咱们快速看下Android启动流程. 与众多基于Linux内核的系统相似, 启动系统时, bootloader启动内核和init进程. init进程分裂出更多名为"daemons(守护进程)"的底层的Linux进程, 诸如android debug deamon, USB deamon等. 这些守护进程处理底层硬件相关的接口.
随后, init进程会启动一个很是有意思的进程---"Zygote". 顾名思义, 这是一个Android平台的很是基础的进程. 这个进程初始化了第一个VM, 而且预加载了framework和众多App所须要的通用资源. 而后它开启一个Socket接口来监听请求, 根据请求孵化出新的VM来管理新的App进程. 一旦收到新的请求, Zygote会基于自身预先加载的VM来孵化出一个新的VM建立一个新的进程.
启动Zygote以后, init进程会启动runtime进程. Zygote会孵化出一个超级管理进程---System Server. SystemServer会启动全部系统核心服务, 例如Activity Manager Service, 硬件相关的Service等. 到此, 系统准备好启动它的第一个App进程---Home进程了.
用户点击Home上的一个App图标, 启动一个应用时:
Click事件会调用startActivity(Intent), 会经过Binder IPC机制, 最终调用到ActivityManagerService. 该Service会执行以下操做:
若是ProcessRecord是null, ActivityManagerService会建立新的进程来实例化目标activity.
ActivityManagerService调用startProcessLocked()方法来建立新的进程, 该方法会经过前面讲到的socket通道传递参数给Zygote进程. Zygote孵化自身, 并调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid.
ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环.
流程图以下:
接下来要作的就是将进程和指定的Application绑定起来. 这个是经过上节的ActivityThread对象中调用bindApplication()方法完成的. 该方法发送一个BIND_APPLICATION的消息到消息队列中, 最终经过handleBindApplication()方法处理该消息. 而后调用makeApplication()方法来加载App的classes到内存中.
流程以下:
通过前两个步骤以后, 系统已经拥有了该application的进程. 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了.
实际调用方法是realStartActivity(), 它会调用application线程对象中的sheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 经过 handleLaunchActivity()来处理该消息.
假设点击的是一个视频浏览的App, 其流程以下: