1. 程式人生 > >Android ClassLoader工作原理學習記錄(一)

Android ClassLoader工作原理學習記錄(一)

最近一直在處理客戶端動態載入、外掛相關的功能,其中的核心便是ClassLoader 類載入器。

不看原理,先看現象

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	int i = 0;
        ClassLoader classLoader = getClassLoader();
        if (classLoader != null) {
            LogUtil.e("classLoader " + i++ + " : " + classLoader.toString());
            while (classLoader.getParent() != null) {
                classLoader = classLoader.getParent();
                LogUtil.e("classLoader " + i++ + " : " + classLoader.toString());
            }
        }
}

得到相關日誌:

classLoader 0 : dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/XXX/base.apk"],nativeLibraryDirectories=[/data/app/XXX/lib/arm, /system/fake-libs, /data/app/XXX/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]]
classLoader 1 : jav[email protected]
從日誌中可以發現,有兩個個ClassLoader例項,一個是 BootClassLoader(系統啟動的時候建立的),另一個是 PathClassLoader(應用啟動時建立的,用於載入 “/data/app/XXX/base.apk” 裡面的類)。
在 Android 系統啟動的時候會建立一個 Boot 型別的 ClassLoader 例項,用於載入一些系統 Framework 層級需要的類,我們的 Android 應用裡也需要用到一些系統的類,所以 APP 啟動的時候也會把這個 Boot 型別的 ClassLoader 傳進來。此外,APP 也有自己的類,這些類儲存在 APK 的 dex 檔案裡面,所以 APP 啟動的時候,也會建立一個自己的 ClassLoader 例項,用於載入自己 dex 檔案中的類。
所以,一個執行的App至少擁有兩個ClassLoader
,那麼這兩個ClassLoader又是如果運作的呢?
檢視Instrumentation原始碼,
public Activity newActivity(ClassLoader cl, String className,Intent intent) 
		throws InstantiationException, IllegalAccessException,ClassNotFoundException {
	return (Activity)cl.loadClass(className).newInstance();
}
可以發現,在建立Activity例項的過程中,呼叫到的是ClassLoader的loadClass方法:
public Class<?> loadClass(String className) throws ClassNotFoundException {
        return loadClass(className, false);
}
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
    //先查詢當前ClassLoader是否已經載入過
    Class<?> clazz = findLoadedClass(className);

    if (clazz == null) {
        ClassNotFoundException suppressed = null;
        try {
	    //再查詢Parent是否載入過
            clazz = parent.loadClass(className, false);
        } catch (ClassNotFoundException e) {
            suppressed = e;
        }

        if (clazz == null) {
            try {
		//如果都沒有載入過,再執行findClass方法,載入相關的class
                clazz = findClass(className);
            } catch (ClassNotFoundException e) {
                e.addSuppressed(suppressed);
                throw e;
            }
        }
    }
    return clazz;
}
所以一個類載入器的載入流程為:
1、先查詢當前ClassLoader是否載入過 
2、如果沒有,再查詢Parent是否載入過 
3、如果繼承路線上的Loader都沒有載入過,則有Child執行載入工作


那Parent與當前Child又是什麼關係呢?

protected ClassLoader() {
    this(getSystemClassLoader(), false);
}

protected ClassLoader(ClassLoader parentLoader) {
    this(parentLoader, false);
}

ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
    if (parentLoader == null && !nullAllowed) {
        throw new NullPointerException("parentLoader == null && !nullAllowed");
    }
    parent = parentLoader;
}
通過原始碼,可以發現,在建立一個構造器例項的時候,必須傳入一個已存在的ClassLoader作為新建立的ClassLoader的ParentLoader;在剛開始的實驗中,可以發現,呼叫PathClassLoader的getParent(),獲取到的就是BootClassLoader。
這樣,一個App中所有的ClassLoader都被關聯起來了。


相關推薦

Android ClassLoader工作原理學習記錄

最近一直在處理客戶端動態載入、外掛相關的功能,其中的核心便是ClassLoader 類載入器。 不看原理,先看現象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate

Android Camera學習記錄 視訊錄製MediaRecorder

第一次寫自己的技術部落格,本人Android菜鳥一枚,寫部落格也只是為了記錄自己學習過的東西,以便以後可以更容找到屬於自己的資料。 最近一直在做Camera的開發,今天主要想將使用Camera錄製視訊的方法記錄下來。 其實網上關於這方面的技術其實都有比較清晰的講解,不過大

android開發-從小工到專家》學習記錄

我對android系統學習的第一本書是《android移動應用基礎教程》-鐵路出版社; 對於android開發的基礎知識有了一定的瞭解,能開發一些基本的安卓端應用,現在進行安卓進階技術的學習,寫此係列部落格以督促自己,希望能提高學習效率,加強學習深度。 第一章  And

linux學習記錄

設備 ima 權限 logs spf style www. 塊設備 alt 1、各種顏色文件的含義 黃色表示設備文件 灰色表示其它文件 白色表示普通文件 綠色表示可執行文件; 紅色表示壓縮文件; 淺藍色表示鏈接文件; 灰色表示其它文件; 紅色閃爍表示鏈接的文件有問題了;

vue學習記錄—— vue開發調試神器vue-devtools安裝

shell gist 項目 擴展工具 code blog manifest false .net 網上有些貼子少了至關重要的一步導致我一直沒裝上, 切記!!install後還需build,且install和build都在vue-devtools文件夾內執行 github下載

微信小程序學習記錄

地址 n) taf forest 對象復制 strong display exp 價格 如何定義一個全局變量: 1,在根目錄下app.js中添加 App({ globalData: { g_isPlayingMusic : false, g_curre

SpringBoot學習記錄

not website snap 對象 mpi method oid pom pid 1. Spring的Java配置方式 Java配置是Spring4.x推薦的配置方式,可以完全替代xml配置。 1.1. @Configuration 和 @Bean Spring的Jav

python+selenium+unittest+pageobject學習記錄

exceptio 單元測試框架 回憶 stc ui自動化 import list 測試的 add 學習selenium已經一個月了,簡單概括一下學習的步驟,方便以後回憶。 一. 自動化測試的一些概念   1.分層的自動化測試:unit-->service-->U

編譯原理學習筆記

.com bubuko image img 記錄 mage 學習 內容 基礎 簡單地瀏覽了一下第一章,主要是基礎性內容,就不記錄了。編譯原理學習筆記(一)

【OpenAI-Gym】學習記錄gym安裝

前言 最近在學習強化學習( Reinforcement Learning ),自學過程包括理論學習部分與演算法學習部分。理論學習部分安利一本書籍 Richard S. Sutton 的 Reinforcement Learning : An Introduction;演算法學習主要為使用

Centos6.10下Open-falcon學習記錄——自定義資料採集、歷史查詢、程序監控

記錄了學習過程,官方文件地址http://book.open-falcon.org/zh_0_2/usage/getting-started.html 另外還看了Open-falcon作者的寫的設計理念的文,見open-falcon編寫的整個腦洞歷程 1 自定義資料採集 自定義的資料要求

redis入門學習記錄

1、linux線上下載Redis ,官網地址:https://redis.io/download目前,最新的Redist版本為redis-5.0.0,使用wget下載 進入/usr/local/src目錄,使用如下命令: wget http://download.redis.io/releases/red

redis入門學習記錄 redis入門學習記錄

繼第一節 redis入門學習記錄(一)之後,我們來學習redis的基本使用。 接下來我們看看/usr/local/redis/bin目錄下的幾個檔案作用是什麼?   redis-benchmark:redis效能測試工具   redis-check-aof:檢查aof日誌的工具   redi

不平等博弈問題學習記錄

聽到博弈問題,第一個想到的想必是用SG函式做的博弈題,就比如Nim遊戲 Nim遊戲:有N堆石子,每次選一堆石子,拿走若干石子(不能不取),先不能取的人輸 定義個SG函式 對於SG函式,大致就記錄兩個東西吧 定義SG函式g(x)=mex{ g(y) |

Spark學習記錄Spark 環境搭建以及worldCount示例

安裝Spark ------------------- 首先,安裝spark之前需要先安裝scala,並且安裝scala的版本一定要是將要安裝的spark要求的版本。比如spark2.1.0 要求scala 2.11系列的版本,不能多也不能少 1.下載spark-2.1.0-bin-hadoop

Java學習記錄java開發環境配置 及第一個執行程式

一. 下載jdk檔案 選擇對應版本下載即可安裝(本文以windows 64位為例) 安裝目錄儘量放至同一空白目錄下 安裝成功! 二. jdk環境配置 1. 點選此電腦右鍵點選屬性 2. 點選高階系統設定

OpenCV學習記錄:使用haar分類器進行人臉識別

https://blog.csdn.net/hongbin_xu/article/details/74202193 OpenCV支援的目標檢測的方法是利用樣本的Haar特徵進行的分類器訓練,得到的級聯boosted分類器(Cascade Classification)。

ES6 思考學習記錄

1.ES模組化如何使用,開發環境如何打包? 使用-> 語法是怎麼樣的。 開發環境-> webpack,rollup... 語法:在export裡面分為export defalut 和export ,export default 就是預

node 學習記錄

第一部分 NODE.JS基礎知識 node.js是一個JavaScript執行平臺,它的顯著特徵是它的非同步和事件驅動機制,以及小巧精悍的標準庫。目前有兩個版本LST以及當前版。 node.js和JavaScript的優勢之一就是單執行緒程式設計模型。多執行緒一般會引入bug。 非阻塞IO:

VRTK學習記錄

一,VRTK環境搭建 前提:匯入SteamVR 1.新建一個空物體改名字為[VRTK_SDK_Manager],並新增VRTK_SDK_Manager指令碼 2…新建一個空物體改名字為[VRTK_SDK_Setup],並新增VRTK_SDK_Setup指令碼 記