Android 進階解密摘要

參照《Android 進階解密》做的摘要。

Android 系統啟動過程

init 進程啟動

Linux 內核加載完成后,它會尋找 init.rc 文件并啟動 init 進程,init 進程的入口函數為 init.cpp 中的 main 函數,可以此為代碼入口跟蹤 init 進程的處理任務。

init 進程啟動后主要做了三件事:

  1. 創建和掛載啟動所需的文件目錄;
  2. 初始化和啟動屬性服務,啟動 ServiceManger 對各種服務進行管理;
  3. 解析 init.rc 配置文件并啟動 Zygote 進程

Zygote 進程啟動

Zygote 進程被稱為孵化器,SystemServer 進程和應用程序進程都是通過 fork Zygote 進程來創建的。

Zygote 進程啟動流程:

  • app_main.cpp:main()
  • AndroidRunTime.cpp:start() → startVm() → startReg()
  • ZygoteInit.java:main() → ZygoteServer.registerServerSocket() → preload() → startSystemServer()
  • ZygoteServer.java:runSelectLoop()

Zygote 進程啟動主要做了一下幾件事:

  1. 創建 APPRuntime 并調用其 strat 方法,啟動 Zygote 進程,即進入 Zygote 進程的入口函數 main,詳情可看 app_main.cpp;
  2. 創建 Java 虛擬機并為 Java 虛擬機注冊 JNI 方法,因此后面 fork Zygote 創建的進程都會持有 Java 虛擬機實例以及 JNI 調用能力;
  3. 通過 JNI 調用 ZygoteInit 的 main 函數進入 Zygote 的 Java 框架層,注意此前包括 init 進程操作等等都是在 C/C++ 層處理,經過上面步驟 2 后才能進入 Java 框架層;
  4. 通過 registerZygoteSocket 方法創建服務端 Socket,并通過 runSelectLoop 方法等待 AMS 的請求來創建新的應用程序進程;
  5. 啟動 SystemServer 進程。

注: 為什么這里需要創建 Socket 進程通訊而不是通過 Binder 進行進程間通訊?因為進程的 fork() 對多線程不友好,僅會將發起調用的線程拷貝到子進程,其他線程都會立即停止,那如果一個線程在 fork() 前占用了某個互斥量,fork() 后被立即停止,這個互斥量就得不到釋放,再去請求該互斥量就會發生死鎖了。盡管 Zygote 沒有采取 Binder 機制,它也不是單線程的,內部還跑了一些虛擬機相關的守護線程,但它在 fork() 前主動停止了其他線程,fork() 后再重新啟動。相比來說自己啟用的線程會比 Binder 線程池的線程更好控制。我猜還有一個問題是如果使用 Binder ,那 fork() 的時候停止了 Binder 線程池就可能導致錯過某個進程的創建請求。

SystemServer 進程啟動

SystemServer 進程啟動流程:

  • ZygoteInit.java:main() → startSystemServer() → Zygote.forkSystemServer() → handleSystemServerProcess() → zygoteInit() → nativeZygoteInit();
  • RuntimeInit.java:applicationInit() → invokeStaticMain()
  • MethodAndArgsCaller.java:run()
  • SystemServer.java:main() → startBootstrapServices() → startCoreServices() → startOtherServices() → Looper.loop()

SystemServer 進程主要用于創建系統服務,如 AMS、WMS 和 PMS 等,并維持這些服務與參與應用的管理和通訊。

SystemServer 進程啟動主要做了一下幾件事:

  1. 啟動 binder 線程池,這樣就可以與其它進程進行通訊;
  2. 創建 SystemServiceManager ,其用于對系統服務進行創建、啟動和生命周期管理;
  3. 啟動各種系統服務,官方分為三大類:引導服務、核心服務和其它服務,具體類別可自行查詢。

Launcher 桌面應用啟動

SystemServer 進程在啟動的過程中會啟動 PackageManagerService,PackageManagerService 啟動后會將系統中的應用程序安裝完成,然后已啟動的 AMS 會將 Launcher 啟動起來。Launcher 啟動后會讀取已安裝的應用顯示到桌面,具體邏輯課查看 Launcher.java 。

Android 系統啟動整體流程

  1. 啟動電源以及 BootLoader:當電源按下時引導芯片會從固定位置加載引導程序 BootLoader,然后 BootLoader 會把系統 OS 拉起來并運行;
    2.** Linux 內核啟動:**當內核啟動時,設置緩存、被保護存儲器、計劃列表、加載驅動。然后會在系統文件中尋找 init.rc 文件啟動 init 進程;
  2. 進程啟動:啟動 init 進程,進而啟動 Zygote 進程接著啟動 SystemServer 進程,最后啟動 Launcher 桌面應用,到此粗略的系統啟動流程完成。

應用程序進程啟動過程

AMS 發送啟動應用程序進程請求流程:

  • AMS.java:startProcessLocked()
  • Process.java:start() → startViaZygote() → openZygoteSocketIfNeeded() → zygoteSendArgsAndGetResult()
  • ZygoteState.java:connect()

Zygote 接受請求并創建應用程序進程流程:

  • ZygoteInit.java:main()
  • SystemServer.java:runSelectLoop()
  • ZygoteConnection.java:runOnce() → Zygote.forkAndSpecialize() → handleChildProc()
  • ZygoteInit.java:zygoteInit() → nativeZygoteInit()
  • RuntimeInit.java:applicationInit() → invokeStaticMain()
  • MethodAndArgsCaller.java:run()
  • ActivityThread.java:main()

解釋:

  1. AMS 的 startProcessLocked() 會將 ActivityThread.java 的全類名作為進程入口參數向下傳導,所以 Zygote 進程創建子進程后才能定位到子進程的入口并執行 ActivityThread.main() ;

  2. 應用程序進程啟動過程中會通過 ZygoteInit.nativeZygoteInit() 創建 Binder 線程池。

四大組件的工作過程

根 Activity 的啟動過程

Launcher 請求 AMS 過程:

  • Launcher.java:startActivitySafely()
  • Activity.java:startActivity() → startActivityForResult()
  • Instrumentation.java:execStartActivity()
  • IActivityManager.java:startActivity()
  • AMS.java:startActivity()

AMS 到 ApplicationThread 的調用過程:

  • AMS.java:startActivity() → startActivityAsUser()
  • ActivityStarter.java:startActivityMayWay() → startActivityLocked() → startActivity() → startActivity() → startActivityUnchecked()
  • ActivityStackSupervisor.java:resumeFocusedStackTopActivityLocked()
  • ActivityStack.java:resumeTopActivityUncheckedLocked() → resumeTopActivityInnerLocked()
  • ActivityStackSupervisor.java:startSpecificActivityLocked() → realStartActivityLocked()
  • ApplicationThread.java:scheduleLaunchActivity()

ActivityThread 啟動 Activity 的過程:

  • ApplicationThread.java:scheduleLaunchActivity()
  • ActivityThread.java:sendMessage()
  • H.java:handleMessage()
  • ActivityThread.java:handleLaunchActivity() → performLaunchActivity()
  • Instrumentation.java:callActivityOnCreate()
  • Activity.java:performCreate() → onCreate()

其中 ActivityThread 調用 performLaunchActivity() 時會通過 createBaseContextForActivity() 創建 ContextImpl 并通過 ClassLoader 創建 Activity 實例,然后通過 activity.attach() 綁定 ContextImpl 并關聯 Window,performLaunchActivity() 結束后還會調用 handleResumeActivity() 將 Activity 的狀態置為 Resume。

Service 的啟動過程

ContextImpl 到 AMS 的調用過程:

  • ContextWrapper.java:startService()
  • ContextImpl.java:startService() → startServiceCommon()
  • IActivityManager.java:startService()
  • AMS.java:startService()

AMS 到 AcitivtyThread 的調用過程:

  • AMS.java:startService()
  • ActiveServices.java:startServiceLocked() → startServiceInnerLocked() → bringUpServiceLocked() → realStartServiceLocked()
  • ApplicationThread.java:scheduleCreateService()
  • ActivityThread.java:sendMessage()
  • H.java:handleMessage()
  • ActivityThread.java:handleCreateService()
  • Service.java:onCreate()

其中 ActivityThread 調用 handleCreateService() 時會通過 ContextImpl.createAppContext 創建 ContextImpl 并通過 ClassLoader 創建 Service 實例,然后通過 service.attach() 綁定 ContextImpl 并初始化 service , 然后調用 service.onCreate() 走 service 的生命周期函數。

Service 的綁定過程

ContextImpl 到 AMS 的調用過程:

  • ContextWrapper.java:bindService()
  • ContextImpl.java:bindService() → bindServiceCommon()
  • IActivityManager.java:bindService()
  • AMS.java:bindService()

AMS 到 AcitivtyThread 的調用過程:

  • AMS.java:bindService()
  • ActiveServices.java:bindServiceLocked() → requestServiceBindingLocked()
  • ApplicationThread.java:scheduleBindService()
  • ActivityThread.java:sendMessage()
  • H.java:handleMessage()
  • ActivityThread.java:handleBindService()
  • AMS.java:publishService()

Service 的綁定過程剩余流程:

  • AMS.java:publishService()
  • ActiveServices.java:publishServiceLocked()
  • InnerConnection.java:connected()
  • ServiceDiapatcher.java:connected()
  • RunConnection.java:run()
  • ServiceDiapatcher.java:doConnected()
  • ServiceConnection.java:onServiceConnected()

廣播的注冊、發送和接收過程

廣播注冊

ContextImpl 到 AMS 的調用過程:

  • ContextWrapper.java:registerReceiver()
  • ContextImpl.java:registerReceiver() → registerReceiverInternal()
  • IActivityManager.java:registerReceiver()
  • AMS.java:registerReceiver()

其中會將 BroadcastReceiver 封裝為 Binder 類型的 IIntentReceiver 傳遞到 AMS ,AMS 會將 IntentFilter 和 IIntentReceiver 封裝為 BroadcastFilter 保存,當收到廣播后會匹配對應的 IntentFilter 然后通過 ApplicationThread 回傳 IIntentReceiver 進行廣播接收者調用。

廣播發送

ContextImpl 到 AMS 的調用過程:

  • ContextWrapper.java:sendBroadcast()
  • ContextImpl.java:sendBroadcast() → sendBroadcast()
  • IActivityManager.java:broadcastIntent()
  • AMS.java:broadcastIntent() → broadcastIntentLocked()

AMS 到 BroadcastReceiver 的調用過程:

  • BroadcastQueue.java:scheduleBroadcastsLocked() → BroadcastHandler.handlerMessage() → deliverToRegisteredReceiverLocked() → performReceiverLocked()
  • ApplicationThread.java:scheduleRegisteredReceiver()
  • InnerReceiver.java:performReceiver()
  • ReceiverDispatcher.java:performReceiver()
  • Args.java:run()
  • BroadcastReceiver.java:onReceiver()

ContentProvider 的啟動過程

query 方法到 AMS 的調用過程:

  • ContentResolver.java:query() → acquireUnstableProvider
  • ApplicationContentResolver.java:acquireUnstableProvider()
  • ActivityThread.java:acquireProvider()
  • IActivityManager.java:getContentProvider()
  • AMS.java:getContentProvider() → getContentProviderImpl()
  • ActivityThread.java:main() → attach()
  • IActivityManager.java:attachApplication()
  • AMS.java:attachApplication()

AMS 啟動 ContentProvider 的過程:

  • AMS.java:attachApplication() → attachApplicationLocked()
  • ApplicationThread.java:bindApplication()
  • ActivityThread.java:sendMessage() → H.handleMessage() → handleBindApplication() → installContentProviders() → installProvider()
  • ContentProvider.java:attachInfo() → onCreate()

理解上下文 Context

Context 意為上下文,經常使用它來啟動四大組件、訪問資源、調用系統服務或者彈出 Toast 、創建 Dialog 之類的。它有兩個子類 ContextWrapper 和 ContextImpl,ContextImpl 負責具體邏輯細節實現,ContextWrapper 則只是對 ContextImpl 進行基本的裝飾,后面的類則繼承自 ContextWrapper 進行進一步功能增強,比如針對主題強化的 ContextThemeWrapper 。Activity、Service、Application 都繼承自 ContextWrapper,所以應用進程的 Context 數量就等于它們三者相加之和。

Application Context 的創建過程:

  • ActivityThread.java:main()
  • LoadedApk.java:makeApplication() → ContextImpl.createAppContext()
  • Instrumentation.java:newApplication()
  • Application.java:attach()
  • ContextWrapper.java:attachBaseContext()

Activity 和 Service 的 Context 創建在上面四大組件啟動中可以看到,最終都是 ContextImpl 創建通過 attachBaseContext 設置的。

理解 ActivityManagerService

ActivityManagerService 簡稱 AMS ,創建于 SystemServer 進程,主要負責四大組件的管理工作。Android 8.0 之前。應用程序與 AMS 通訊使用的是原始的 Binder 通訊,相對麻煩,8.0 開始則改為了使用 AIDL 接口,簡化了代碼交互邏輯。

AMS 重要的數據結構

ActivityRecord

內部記錄了 Activity 的所有信息,包括 AMS 的引用、AndroidManifest 節點信息、Activity 狀態、Activity 資源信息和 Activity 進程相關信息以及 TaskRecord。

TaskRecord

就是我們通常所說的 Activity 任務棧,里面保存了棧中的各個 Activity 的 ActivityRecord 信息。

ActivityStack

ActivityStack 是一個管理類,用來管理系統所有 Activity,并按不同的狀態進行分類。它內部存儲各種不同狀態的列表,列表的元素主要有 ActivityRecord 和 TaskRecord,比如 mTaskHistory 列表存儲的是所有沒有被銷毀的 Activity 任務棧 TaskRecord。

理解 WindowManager

Window 是一個每一個界面的載體,具體的實現為 PhoneWindow,它對 View 進行管理;WindowManager 繼承接口 ViewManager ,實現類為 WindowManagerImpl,主要負責與 WindowManagerService 通信,WindowManagerService 則負責 Window 的具體管理工作。如果要對 Window 進行添加、更新和刪除操作,需要借助 WindowManager 將具體的工作交由 WMS 來處理,WindowManager 和 WMS 通過 Binder 進行跨進程通信。

Activity 的 PhoneWindow 創建是在調用 Activity.attach() 方法內部創建的,接著PhoneWindow 又通過 setWindowManager 創建一個 WindowManagerImpl 實例,而 WindowManagerImpl 的內部又會將具體實現委托給 WindowManagerGlobal, WindowManagerGlobal 是一個單例,一個進程中只有一個 WindowManagerGlobal 實例。

Window 的屬性

Window 的類型

Window 的主要分為三大類型,分別是 Application Window(應用程序窗口),Sub Window(子窗口)、System Window(系統窗口)

  1. 應用程序窗口:Activity 就是一個典型的應用程序窗口,應用程序窗口的 Type 范圍是 1-99 ,根據 Type 值的不同又會分為很多種應用程序窗口,具體可查閱資料或源碼;
  2. 子窗口:子窗口無法獨立存在,需要依附在其它窗口才可以,PopupWindow 就屬于子窗口,子窗口的 Type 范圍是 1000-1999;
  3. 系統窗口: Toast、出入法窗口、系統音量條窗口、系統錯誤窗口都屬于系統窗口,系統窗口的 Type 范圍是 2000-2999 ;

Window 的顯示次序

如果把手機屏幕虛擬的用 X、Y、Z 軸表示,其中 Z 軸垂直于屏幕,則 Window 的顯示次序可以看作是在 Z 軸上的次序,通常 Type 值越大,則 Window 的顯示就越靠近用戶,所以應用程序窗口 < 子窗口 < 系統窗口,< 代表顯示層級。

Window 的操作

Activity 的 Window 添加過程:

  • ActivityThread.java:handleResumeActivity()
  • WindowManagerImpl.java:addView()
  • WindowManagerGlobal.java:addView()
  • ViewRootImpl.java:setView()
  • Session.java:addToDisPlay()
  • WMS.java:addWindow()

其中 WindowManagerGlobal 保存了每個窗口對應的 View 和 ViewRootImpl,具體的添加過程則是通過 ViewRootImpl 來進行的。ViewRootImpl 身負了很多職責,主要有一下幾點:

  • View 樹的根并管理 View 樹;
  • 觸發 View 的測量、布局和繪制;
  • 輸入事件的中轉站;
  • 管理 Surface;
  • 負責與 WMS 進行進程間通信。

Window 的更新過程:

  • WindowManagerImpl.java:updateViewLayout()
  • WindowManagerGlobal.java:updateViewLayout()
  • ViewRootImpl.java:setLayoutParams() -> scheduleTraversals() -> doTraversal() -> performTraversals() -> relaoutWindow()
  • Session.java:relayout()
  • WMS.java:relayoutWindow()

其中 ViewRootImpl 在 performTraversals() 調用 relaoutWindow() 后就會繼續往下執行 View 的繪制三部曲: performMeasure() -> performLayout() -> performDraw() ;

理解 WindowManagerService

WMS 的職責

WMS 是 Android 中重要的服務,它有很多職責,每個職責都會涉及重要且復雜的系統:

  1. 窗口管理:它是窗口的管理者,負責窗口的啟動、添加和刪除,還有對窗口的大小和顯示層級進行管理;
  2. 窗口動畫:窗口動畫有 WMS 的動畫子系統來負責,動畫子系統的管理者為 WindowAnimator ;
  3. 輸入系統的中轉站:通過對窗口的觸摸從而產生觸摸事件,InputManagerService(IMS)會對觸摸事件進行處理,它會尋找一個最合適的窗口來處理觸摸反饋信息,WMS 是窗口的管理者,它作為輸入系統的中轉站再合適不過了;
  4. Surface 管理:窗口并不具備繪制的功能,因此每個窗口都需要有一塊 Surface 來供自己繪制,為每個窗口分配 Surface 是由 WMS 來完成的。

WMS 的創建過程

WMS 的創建過程依次分為三個線程進行處理:

  1. system_server:startCoreService() -> WMS.main() -> WMS.displayReady()
  2. android.display:new WMS() -> WMS.initPolicy()
  3. android.ui:PWM.init()

android.display 的優先級比 system_server 高,所以 system_server 會等待 android.display 處理完畢,同理 android.display 也會等待 android.ui 線程處理完畢,具體實現可查看源碼。

WMS 的重要成員

mSessions: ArraySet

mSessions 的元素是 Session,它主要用于進程間通信,每個應用程序進程想和 WMS 進行通信都需要經過 Session ,并且每個應用程序進程都會對應一個 Session ,WMS 保存這些 Session 用來記錄所有向 WMS 提出窗口管理服務的客戶端。

mFinishedStarting: ArrayList

mFinishedStarting 的元素是 AppWindowToken,它是 WindowToken 的子類,WindowToken 主要有兩個作用:

  1. 窗口令牌,當應用程序想要向 WMS 申請新創建一個窗口,則需要向 WMS 出示有效的 WindowToken。所以每個 Activity 都對應一個 APPWindowToken;
  2. WindowToken 會將同一個組件(比如同一個 Activity )的窗口(WindowState)集合在一起,方便管理,即 Dialog 的窗口和 Activity 的窗口是放在一起管理的。

mFinishedStarting 存儲已經完成啟動的應用程序窗口的 AppWindowToken 列表。

Window 的 WMS 添加過程

Window 的 WMS 添加過程主要集中在 addWindow() 方法,該方法主要做了四件事:

  • 對所要添加的窗口進行檢查,如果窗口不滿足一些條件,就不會再執行下面的代碼邏輯;
  • WindowToken 相關的處理,比如有的窗口類型需要提供 WindowToken,沒有提供的話就不會執行下面的代碼邏輯,有的窗口類型則需要由 WMS 隱式創建 WindowToken;
  • WindowState 的創建和相關處理,將 WindowToken 和 WindowState 相關聯;
  • 創建和配置 DisplayContent,完成窗口添加到系統前的準備工作。

Window 的 刪除過程

Window 的刪除過程:

  • WindowManagerImpl.java:removeView()
  • WindowManagerGlobal.java:removeView() -> removeViewLocked()
  • ViewRootImpl.java:die() -> doDie() (doDie 內部會遍歷子 View 調用 dispatchDetachedFromWindow())
  • WindowManagerGlobal.java:doRemoveView()
  • WMS.java:relayoutWindow()

dispatchDetachedFromWindow 流程:

  • ViewRootImpl.java:dispatchDetachedFromWindow()
  • Session.java:remove()
  • WMS.java:removeWindow() -> removeIfPossible() -> removeImmediately()

Window 的刪除邏輯比較復雜,以下作簡單總結:

  • 檢查刪除線程的正確性,即只能是創建 View 的線程(通常稱為 UI 線程,不一定是主線程)才能操作 View;
  • 從 ViewRootImpl 列表、布局參數列表和 View 列表中刪除與 View 對應的元素;
  • 判斷是否可以直接執行刪除操作,如果不能就推遲刪除操作;
  • 執行刪除操作,清理和釋放與 View 相關的一切資源。

JNI 原理

JNI 是 Java 世界和 Native 世界的橋梁。

Native 方法注冊

Native 方法注冊分為靜態注冊和動態注冊,其中靜態注冊多用于 NDK 開發,而動態注冊多用于 Framework 開發。

靜態注冊使用的是約定大于配置的思想,通過包名+類名+方法名的格式將 Java 方法和 JNI 函數建立關聯

動態注冊則需要手動將 Java 方法和 JNI 函數進行綁定注冊,通常會在 JNI_OnLoad 函數中進行。

方法簽名

JNI 的方法簽名的格式為: (參數簽名格式...)返回值簽名格式

解析 JNIEnv

JNIEnv 是 Native 世界中 Java 環境的代表,通過 JNIEnv *指針可以在 Native 世界中訪問 Java 世界的代碼進行操作,它只在創建它的線程中有效,不能跨線程傳遞,因此不同線程的 JNIEnv 是彼此獨立的,JNIEnv 的主要作用有以下兩點:

  • 調用 Java 的方法。
  • 操作 Java (操作 Java 中的變量和對象等)。

JNIEnv 是一個結構體,其內部又包含了 JNINativeInterface。JNIEnv 中常用函數很多,這里列舉三個,FindClass 用來找到 Java 中指定名稱的類,GetMethodID 用來得到 Java 中的方法,GetFieldID 用來得到 Java 中的成員變量。

引用類型

JNI 的引用類型分別是本地引用(Local References)、全局引用(Global References)和弱全局引用(Weak Global References)。

本地引用:

  • 當 Native 函數返回時,這個本地引用就會被自動釋放。
  • 只在創建它的線程中有效,不能夠跨線程使用。
  • 局部引用是 JVM 負責的引用類型,受 JVM 管理。

全局引用:

  • 在 native 函數返回時不會被自動釋放,因此全局引用需要手動來進行釋放,并且不會被 GC 回收。
  • 全局引用是可以跨線程使用的。
  • 全局引用不受到 JVM 管理。

弱全局引用:

  • 弱全局引用是一種特殊的全局引用,它和全局引用的特點相似,不同的是弱全局引用是可以被 GC 回收的,弱全局引用被 GC 回收之后會只想 NULL。

ClassLoader

Android 中的 ClassLoader 類型和 Java 中的 ClassLoader 類型類似,也分為兩種類型,分別是系統類加載器和自定義類加載。其中系統類加載器主要包括 3 種,分別是 BootClassLoader 、 PathClassLoader 和 DexClassLoader。

1.BootClassLoader

Android 系統啟動時會使用 BootClassLoader 來預加載常用類,與 JDK 中的 BootClassLoader 不同,它不是由 C/C++ 代碼實現的,而是由 Java 實現的,BootClassLoader 是 ClassLoader 的內部類,進繼承自 ClassLoader。

2.DexClassLoader

DexClassLoader 可以加載 dex 文件以及包含 dex 的壓縮文件(apk 和 jar 文件),不管加載哪種文件,最終都要加載 dex 文件。

3.DexClassLoader

Android 系統使用 PathClassLoader 來加載系統類和應用程序的類。

PathClassLoader 和 DexClassLoader 都是繼承自 BaseDexClassLoader,所以它們的構造方法都有如下 4 個參數:

  • dexPath:dex 相關文件路徑集合,多個路徑用文件分隔符分割,默認文件分隔符為":"。
  • optimizedDirectory:解壓的 dex 文件存儲路徑,這個路徑必須是一個內部存儲路徑,即應用程序的內部存儲空間。
  • librarySearchPath:包含 C/C++ 庫的路徑集合,多個路徑用文件分隔符分割,可以為 null。
  • parent:父加載器。

PathClassLoader 中的 optimizedDirectory 固定為 /data/dalvik-cache,所以 PathClassLoader 無法定義解壓的 dex 文件存儲路徑,因此 PathClassLoader 通常用來加載已經安裝的 apk 的 dex 文件(安裝的 apk 的 dex 文件會存儲在 /data/dalvik-cache 中)。DexClassLoader 則通常用于插件化中加載新的 dex 文件。

ClassLoader 查找流程:

  • ClassLoader:loadClass()
  • BaseDexClassLoader.java:findClass()
  • DexPathList.java:findClass()
  • Element.java:findClass()
  • DexFile.java:loadClassBinaryName()

BootClassLoader 和 PathClassLoader 都是在 Zygote 進程的 ZygoteInit 中創建的。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372