爲了便於閱讀, 應邀將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, 其流程以下: