首頁>技術>

閱讀本文大約需要花費1小時。

文章的內容主要還是從原始碼進行分析,雖然又臭又長,但是如果想要學習Android系統原始碼,這是必要走的路,沒有捷徑。

相對於碎片學習,我更傾向於靜下心來花費1個小時認真的學習一段內容。

上一節我們講完了Launcher的啟動流程,這一節來看看應用程序的建立過程以及Zygote的fork流程。

系列文章:

1.概述

上一節我們學習了Launcher的啟動流程。這一節來介紹下應用程序的建立過程以及Zygote Fork的過程。

在上一節Launcher的啟動中我們知道了,手機的桌面其實就是Launcher程序,裡面的應用圖示都是Launcher通過ListView進行展示。

在分析之前,我們簡單區分一下程序和執行緒的概念。

在Android中通過Logcat抓取log時,存在PID和TID兩個概念。

PID:Process ID,程序ID

TID: Thread ID,執行緒ID

每個Android都是一個程序,每個程序有一個或多個執行緒

程序:

是併發執行的程式在執行過程中分配和管理資源的基本單位,是一個動態概念,競爭計算機系統資源的基本單位。

當我們點選某個應用的圖示時,必須建立一個程序,該程序是由Zygote fork出來的,程序具有獨立的資源空間,用於承載App上執行的各種Activity/Service等元件。

執行緒:

是程序的一個執行單元,是程序內科排程實體。比程序更小的獨立執行的基本單位。執行緒也被稱為輕量級程序。

每個應用有多個執行緒,例如UI展示屬於UI主執行緒,一些通訊過程屬於獨立執行緒,通常JAVA中使用new Thread().start()來建立一個新的執行緒。

該執行緒並沒有自己獨立的地址空間,而是與其所在程序之間資源共享。

程序執行緒的區別

地址空間:同一程序的執行緒共享本程序的地址空間,而程序之間則是獨立的地址空間。資源擁有:同一程序內的執行緒共享本程序的資源,但是程序之間的資源是獨立的。一個程序崩潰後,在保護模式下不會對其他程序產生影響,但是一個執行緒崩潰整個程序都死掉。所以多程序要比多執行緒健壯。程序切換時,消耗的資源大,效率高。所以涉及到頻繁的切換時,使用執行緒要好於程序。同樣如果要求同時進行並且又要共享某些變數的併發操作,只能用執行緒不能用程序。執行過程:每個獨立的程序有一個程式執行的入口、順序執行序列和程式入口。但是執行緒不能獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制。執行緒是處理器排程的基本單位,但是程序不是。兩者均可併發執行。2.核心原始碼3.架構

App發起程序:點選一個桌面應用(例如微信),Launcher 載入應用, LauncherActivity收到觸發事件,組裝Intent,通過binder傳送訊息給SystemServer程序,呼叫Activity的startActivity()來啟動程序,啟動Activity時,受ActivityManagerService-AMS的服務控制,AMS屬於SystemServer程序,因此SystemServer進行會通過Process 來向Zygote傳送一個Socket。

Zygote有一個無限迴圈,一直在等待Socket請求,收到SystemServer發來新的Socket請求後,Zygote呼叫系統的fork函式來孵化一個新的程序,比如這裡的微信。

3.1 程序建立圖

3.2 Zygote Fork圖

Zygote呼叫系統的fork()函式,孵化出一個新的程序,fork()採用copy-on-write機制,有些類如果不做改變,甚至都不用複製,子程序可以和父程序共享這部分資料,從而省去不少記憶體的佔用。

4.原始碼分析

應用的啟動共分以下四個步驟完成:

點選桌面的圖示,Launcher呼叫系統的startActivity進行啟動Activity,此時的動作在Launcher程序中ATM\\AMS 進行Activity的處理,組裝message,通過socket傳送給SocketZygote收到SystemServer發來的訊息,進行訊息拆分,再呼叫系統的fork()函式,進行進行孵化操作。進入ActivityThread的main(),完成最終應用程序的的onCreate操作

接下來我們根據這四個步驟來進行詳細的原始碼分析.

說明:桌面圖示按照5*5或者6*6的方式進行排列,這其實是Launcher程序展示的ListView,每個應用圖示填入其中,點選圖示進入Launcher的點選事件處理

原始碼:

4.1.1 [Activity.java]

startActivity()

說明:這裡比較簡單,呼叫

startActivityForResult()

原始碼:

4.1.2 [Activity.java]

startActivityForResult()

說明:不難發現,不論有沒有父Activity,最終都交給了 Instrumentation 來開啟

原始碼:

4.1.3 [Instrumentation.java]

execStartActivity()

說明:Binder 呼叫 ActivityTaskManagerService-ATM 來啟動 Activity

原始碼:

從下面程式碼可以看到,IActivityTaskManager其實獲得的是activity_task對應服務的Binder物件,

即是ActivityTaskManagerService-ATM

4.2 第二階段:ATM\\AMS 進行Activity的處理

呼叫棧如下:

4.2.1 [ActivityTaskManagerService.java]

startActivity()

說明:這裡很簡單,直接呼叫startActivityAsUser()

原始碼:

4.2.2 [ActivityTaskManagerService.java]

startActivityAsUser()

說明:獲取 ActivityStarter 物件,最終呼叫ActivityStarter的execute()

原始碼:

4.2.3 [ActivityStarter.java] execute()

說明:根據[4.2.2]中呼叫了setMayWait,因此這裡的mRequest.mayWait為true

原始碼:

4.2.4 [ActivityStarter.java]

startActivityMayWait()

說明:呼叫startActivity()來啟動Activity

原始碼:

4.2.5 [ActivityStarter.java]

startActivity()

說明:延時佈局,然後通過startActivityUnchecked()來處理啟動標記 flag ,要啟動的

4.2.6 [RootActivityContainer.java]

resumeFocusedStacksTopActivities()

說明:獲取棧頂的Activity,恢復它

原始碼:

4.2.7 [ActivityStackSupervisor.java]

startSpecificActivityLocked()

說明:釋出訊息以啟動程序,以避免在ATM鎖保持的情況下呼叫AMS時可能出現死鎖,最終呼叫到ATM的startProcess()

原始碼:

4.2.8 [ActivityManagerService.java]

startProcess()

說明:一路呼叫Process start(),最終到ZygoteProcess的

attemptUsapSendArgsAndGetResult(),用來fork一個新的Launcher的程序

原始碼:

呼叫棧如下:

4.2.9 [ZygoteProcess.java]

attemptZygoteSendArgsAndGetResult()

說明:通過Socket連線Zygote程序,把之前組裝的msg發給Zygote,其中processClass ="android.app.ActivityThread",通過Zygote程序來Fork出一個新的程序,

並執行 "android.app.ActivityThread"的main方法

原始碼:

4.3 第三階段 Zygote Fork 應用程序

說明:Zygote的啟動過程我們前面有詳細講到過。

SystemServer的AMS服務向啟動Home Activity發起一個fork請求,Zygote程序通過Linux的fork函式,孵化出一個新的程序。

由於Zygote程序在啟動時會建立Java虛擬機器,因此通過fork而建立的Launcher程式程序可以在內部獲取一個Java虛擬機器的例項拷貝。

fork採用copy-on-write機制,有些類如果不做改變,甚至都不用複製,子程序可以和父程序共享這部分資料,從而省去不少記憶體的佔用。

呼叫棧如下:

4.3.1 [ZygoteInit.java] main()

說明:Zygote先fork出SystemServer程序,接著進入迴圈等待,用來接收Socket發來的訊息,用來fork出其他應用程序,比如Launcher

原始碼:

4.3.2 [ZygoteConnection.java]

processOneCommand()

說明:通過 forkAndSpecialize()來fork出Launcher的子程序,並執行handleChildProc,進入子程序的處理

原始碼:

4.3.3 [Zygote.java] forkAndSpecialize

說明:主要是呼叫dalvik中ZygoteHooks的preFrok進行預處理,再呼叫postForkCommon進行完成的程序fork

原始碼:

4.3.3.1 [ZygoteHooks.java] preFork()

說明:Zygote程序有4個Daemon子執行緒分別是

HeapTaskDaemon、

ReferenceQueueDaemon、

FinalizerDaemon、

FinalizerWatchdogDaemon

preFork()預處理主要是先停止4個子執行緒,等待所有的子執行緒結束,最後完成gc堆的初始化工作

Zygote子執行緒如下圖所示:

原始碼:

4.3.3.2 [Daemons.java] stop()

說明:此處守護執行緒Stop方式是先呼叫目標執行緒interrrupt()方法,然後再呼叫目標執行緒join()方法,等待執行緒執行完成

停止4個子執行緒,分別是:Java堆整理執行緒;引用佇列執行緒;析構執行緒;析構監控執行緒

原始碼:

4.3.3.3 [ZygoteHooks.java]

waitUntilAllThreadsStopped()

說明:等待所有子執行緒結束

原始碼:

4.3.4 [ZygoteHooks.java]

nativePreFork()

通過JNI最終呼叫的是以下方法:

[dalvik_system_ZygoteHooks.cc] ZygoteHooks_nativePreFork()

說明:進行堆的一些預處理

原始碼:

4.3.4.1 [runtime.cpp] PreZygoteFork()

說明:堆的初始化工作,屬於虛擬機器的範疇,想理解的可以深挖一下

原始碼:

4.3.5 [Zygote.java]

nativeForkAndSpecialize()

通過JNI最終呼叫的是以下方法:

[com_android_internal_os_Zygote.cpp] com_android_internal_os_Zygote_nativeForkAndSpecialize

說明: fork 子程序

原始碼:

4.3.5.1 [com_android_internal_os_Zygote.cpp]

ForkCommon()

說明:呼叫系統的fork()進行 應用程序的孵化操作,採用copy-on-write的機制,使得應用程序與Zygote共享部分資料,減少記憶體的佔用

原始碼:

4.3.5.2 [com_android_internal_os_Zygote.cpp]

SpecializeCommon()

說明:進行程序的一些資源處理,selinux許可權處理,並呼叫Zygote的callPostForkChildHooks()

原始碼:

4.3.5.3 [Zygote.java]

callPostForkChildHooks()

說明:JAVA堆執行緒的一些處理

原始碼:

建立JAVA的執行緒池,設定訊號處理,啟動JDWP執行緒

4.3.6 [ZygoteHooks.java] postForkCommon()

說明:在fork新程序後,啟動Zygote的4個Daemon執行緒,java堆整理,引用佇列,以及析構執行緒。

原始碼:

啟動Zygote的4個新的子執行緒

4.3.7 [ZygoteConnection.java]

handleChildProc()

說明:進行子程序的操作,最終獲得需要執行的ActivityThread的main()

原始碼:

zygoteInit 進行一些環境的初始化、啟動Binder程序等操作

把之前傳來的"android.app.ActivityThread" 傳遞給findStaticMain

通過反射,拿到ActivityThread的main()方法

把反射得來的ActivityThread main()入口返回給ZygoteInit的main,通過caller.run()進行呼叫

至此,Zygote fork程序的操作全部完成,下一步進入JAVA世界,進行真正的Activity的啟動流程。

4.4 第四階段 進入應用程序,啟動Activity的onCreate()

呼叫棧如下:

4.4.1 [ActivityThread.java] main()

說明: 主執行緒處理, 建立ActivityThread物件,呼叫attach進行處理,最終進入Looper迴圈

原始碼:

呼叫ActivityThread的attach進行處理

4.4.2 [ActivityManagerService.java] attachApplication()

說明:清除一些無用的記錄,最終呼叫ActivityStackSupervisor.java的 realStartActivityLocked(),進行Activity的啟動

原始碼:

4.4.3 [ActivityStackSupervisor.java]

realStartActivityLocked()

說明:真正準備去啟動Activity,通過clientTransaction.addCallback把LaunchActivityItem的obtain作為回撥引數加進去,再呼叫

ClientLifecycleManager.scheduleTransaction()得到LaunchActivityItem的execute()方法進行最終的執行

參考上面的第四階段的呼叫棧流程:

原始碼:

4.4.4 [TransactionExecutor.java] execute()

說明:執行之前realStartActivityLocked()中的

clientTransaction.addCallback

呼叫棧:

原始碼:

4.4.5 [ActivityThread.java]

handleLaunchActivity()

說明:主要乾了兩件事,第一件:初始化WindowManagerGlobal;第二件:呼叫performLaunchActivity方法

原始碼:

4.4.6 [ActivityThread.java]

performLaunchActivity()

說明:獲取ComponentName、Context,反射建立Activity,設定Activity的一些內容,比如主題等;

最終呼叫callActivityOnCreate()來執行Activity的onCreate()方法

原始碼:

callActivityOnCreate先執行activity onCreate的預處理,再去呼叫Activity的onCreate,最終完成Create建立後的內容處理

performCreate()主要呼叫Activity的onCreate()

至此,看到了我們最熟悉的Activity的onCreate(),應用啟動的啟動完成,應用程式被真正的呼叫起來。

5.總結

通過上面一系列的流程,我們理解了應用程序的建立流程,以及Zygote fork這些應用程序的流程。

主要分為4步完成:

點選桌面的圖示,Launcher呼叫系統的startActivity進行啟動Activity,此時的動作在Launcher程序中通過Binder向SystemServer進行傳送訊息,讓ATM\\AMS 進行Activity的處理,組裝message,通過socket傳送給Socket,此時動作在SystemServer程序中Zygote收到SystemServer發來的訊息,進行訊息拆分,再呼叫系統的fork()函式,進行進行孵化操作,此時動作在Zygote程序中進入ActivityThread的main(),完成最終應用程序的的onCreate操作,該步動作處於新建立的應用程序中

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 2020從使用螞蟻筆記開始