1. 程式人生 > >Android ClassLoader詳解

Android ClassLoader詳解

我們知道不管是外掛化還是元件化,都是基於系統的ClassLoader來設計的。只不過Android平臺上虛擬機器執行的是Dex位元組碼,一種對class檔案優化的產物,傳統Class檔案是一個Java原始碼檔案會生成一個.class檔案,而Android是把所有Class檔案進行合併,優化,然後生成一個最終的class.dex,目的是把不同class檔案重複的東西只需保留一份,如果我們的Android應用不進行分dex處理,最後一個應用的apk只會有一個dex檔案。

Android平臺的ClassLoader


Android中的ClassLoader

Android中類載入器有BootClassLoader,URLClassLoader,
PathClassLoader,DexClassLoader,BaseDexClassLoader,等都最終繼承自java.lang.ClassLoader。

  • ClassLoader

    java.lang.ClassLoader是所有ClassLoader的最終父類。構造方法主要以下兩種
    1.傳入一個父類構造器

    實際構造器2.無參預設構造法





    無參構造器可以看出ClassLoader主要就是傳入一個父構造器,而且一般父構造器不能為空,不像java虛擬機器裡父構造器為空時預設的父構造器為Bootstrap ClassLoader。Android中預設無父構造器傳入的情況下,預設父構造器為一個PathClassLoader且此PathClassLoader父構造器為BootClassLoader。
    ClassLoader中重要的方法是loadClass(String name),其他的子類都繼承了此方法且沒有進行復寫。

    可以看出在載入類時首先判斷這個類是否之前被載入過,如果有則直接返回,如果沒有則首先嚐試讓parent ClassLoader進行載入,載入不成功才在自己的findClass中進行載入。這和java虛擬機器中常見的雙親委派模型一致的,這種模型並不是一個強制性的約束模型,比如你可以繼承ClassLoader複寫loadCalss方法來破壞這種模型,只不過雙親委派模是一種被推薦的實現類載入器的方式,而且jdk1.2以後已經不提倡使用者在覆蓋loadClass方法,而應該把自己的類載入邏輯寫到findClass中。
  • BootClassLoader

    和java虛擬機器中不同的是BootClassLoader是ClassLoader內部類,由java程式碼實現而不是c++實現,是Android平臺上所有ClassLoader的最終parent,這個內部類是包內可見,所以我們沒法使用。
  • URLClassLoader

    只能用於載入jar檔案,但是由於 dalvik 不能直接識別jar,所以在 Android 中無法使用這個載入器。
  • BaseDexClassLoader

    PathClassLoader和DexClassLoader都繼承自BaseDexClassLoader,其中的主要邏輯都是在BaseDexClassLoader完成的。這些原始碼在java/dalvik/system中。
    先看下BaseDexClassLoader的構造方式:



    BaseDexClassLoader的建構函式包含四個引數,分別為:
    • dexPath,指目標類所在的APK或jar檔案的路徑,類裝載器將從該路徑中尋找指定的目標類,該類必須是APK或jar的全路徑.如果要包含多個路徑,路徑之間必須使用特定的分割符分隔,特定的分割符可以使用System.getProperty(“path.separtor”)獲得。上面"支援載入APK、DEX和JAR,也可以從SD卡進行載入
      "指的就是這個路徑,最終做的是將dexPath路徑上的檔案ODEX優化到內部位置optimizedDirectory,然後,再進行載入的。
    • File optimizedDirectory,由於dex檔案被包含在APK或者Jar檔案中,因此在裝載目標類之前需要先從APK或Jar檔案中解壓出dex檔案,該引數就是制定解壓出的dex 檔案存放的路徑。這也是對apk中dex根據平臺進行ODEX優化的過程。其實APK是一個程式壓縮包,裡面包含dex檔案,ODEX優化就是把包裡面的執行程式提取出來,就變成ODEX檔案,因為你提取出來了,系統第一次啟動的時候就不用去解壓程式壓縮包的程式,少了一個解壓的過程。這樣的話系統啟動就加快了。為什麼說是第一次呢?是因為DEX版本的也只有第一次會解壓執行程式到 /data/dalvik-cache(針對PathClassLoader)或者optimizedDirectory(針對DexClassLoader)目錄,之後也是直接讀取目錄下的的dex檔案,所以第二次啟動就和正常的差不多了。當然這只是簡單的理解,實際生成的ODEX還有一定的優化作用。ClassLoader只能載入內部儲存路徑中的dex檔案,所以這個路徑必須為內部路徑。
    • libPath,指目標類中所使用的C/C++庫存放的路徑
    • classload,是指該裝載器的父裝載器,一般為當前執行類的裝載器,例如在Android中以context.getClassLoader()作為父裝載器。
  • DexClassLoader

    在看下DexClassLoader和PathClassLoader的構造器:


    DexClassLoader支援載入APK、DEX和JAR,也可以從SD卡進行載入。
    上面說dalvik不能直接識別jar,DexClassLoader卻可以載入jar檔案,這難道不矛盾嗎?其實在BaseDexClassLoader裡對".jar",".zip",".apk",".dex"字尾的檔案最後都會生成一個對應的dex檔案,所以最終處理的還是dex檔案,而URLClassLoader並沒有做類似的處理。
    一般我們都是用這個DexClassLoader來作為動態載入的載入器。
  • PathClassLoader



    很簡單明瞭,可以看出PathClassLoader沒有將optimizedDirectory置為Null,也就是沒設定優化後的存放路徑。其實optimizedDirectory為null時的預設路徑就是/data/dalvik-cache 目錄。
    PathClassLoader是用來載入Android系統類和應用的類,並且不建議開發者使用。
    很多部落格裡說PathClassLoader只能載入已安裝的apk的dex,其實這說的應該是在dalvik虛擬機器上,在art虛擬機器上PathClassLoader可以載入未安裝的apk的dex(在art平臺上已驗證),然而在/data/dalvik-cache 確未找到相應的dex檔案,懷疑是art虛擬機器判斷apk未安裝,所以只是將apk優化後的odex放在記憶體中,之後進行釋放,這只是個猜想,希望有知道的可以告知一下。因為dalvik上無法使用,所以我們也沒法使用。

ClassLoader載入class的過程

#BaseDexClassLoader
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException { 
    Class clazz = pathList.findClass(name);
    if (clazz == null) { 
        throw new ClassNotFoundException(name); 
    } 
    return clazz;
}
#DexPathList
public Class findClass(String name) { 
    for (Element element : dexElements) { 
        DexFile dex = element.dexFile;
        if (dex != null) { 
            Class clazz = dex.loadClassBinaryName(name, definingContext); 
          if (clazz != null) { 
              return clazz; 
          } 
        } 
    } 
    return null;
}
#DexFile
public Class loadClassBinaryName(String name, ClassLoader loader) { 
    return defineClass(name, loader, mCookie);
}
private native static Class defineClass(String name, ClassLoader loader, int cookie);

可以看出,BaseDexClassLoader中有個pathList物件,pathList中包含一個DexFile的陣列dexElements,由上面分析知道,dexPath傳入的原始dex(.apk,.zip,.jar等)檔案在optimizedDirectory資料夾中生成相應的優化後的odex檔案,dexElements陣列就是這些odex檔案的集合,如果不分包一般這個陣列只有一個Element元素,也就只有一個DexFile檔案,而對於類載入呢,就是遍歷這個集合,通過DexFile去尋找。最終呼叫native方法的defineClass。

ART虛擬機器的相容性問題

Android Runtime(縮寫為ART),在Android 5.0及後續Android版本中作為正式的執行時庫取代了以往的Dalvik虛擬機器。ART能夠把應用程式的位元組碼轉換為機器碼,是Android所使用的一種新的虛擬機器。它與Dalvik的主要不同在於:Dalvik採用的是JIT技術,位元組碼都需要通過即時編譯器(just in time ,JIT)轉換為機器碼,這會拖慢應用的執行效率,而ART採用Ahead-of-time(AOT)技術,應用在第一次安裝的時候,位元組碼就會預先編譯成機器碼,這個過程叫做預編譯。ART同時也改善了效能、垃圾回收(Garbage Collection)、應用程式除錯以及效能分析。但是請注意,執行時記憶體佔用空間較少同樣意味著編譯二進位制需要更高的儲存。
ART模式相比原來的Dalvik,會在安裝APK的時候,使用Android系統自帶的dex2oat工具把APK裡面的.dex檔案轉化成OAT檔案,OAT檔案是一種Android私有ELF檔案格式,它不僅包含有從DEX檔案翻譯而來的本地機器指令,還包含有原來的DEX檔案內容。這使得我們無需重新編譯原有的APK就可以讓它正常地在ART裡面執行,也就是我們不需要改變原來的APK程式設計介面。ART模式的系統裡,同樣存在DexClassLoader類,包名路徑也沒變,只不過它的具體實現與原來的有所不同,但是介面是一致的。實際上,ART執行時就是和Dalvik虛擬機器一樣,實現了一套完全相容Java虛擬機器的介面。






相關推薦

Android ClassLoader

我們知道不管是外掛化還是元件化,都是基於系統的ClassLoader來設計的。只不過Android平臺上虛擬機器執行的是Dex位元組碼,一種對class檔案優化的產物,傳統Class檔案是一個Java原

Android中的dex、apk、ClassLoader

dalvik載入、執行過程 我們編寫java程式碼都是.java格式的,但是jvm並不能識別.java檔案,它只能載入、執行.class檔案,所以我們要通過javac命令將.java檔案編譯成.class檔案,然後通過java命令執行.class檔案。其實,如

ClassLoader

normal class對象 logs 目錄 left 進行 family lib 時間 1. classLoader是什麽? ClassLoader是類的加載器,用於加載class對象到JVM中的,分為2種,啟動類加載器和實際類加載器. 2. ClassLoader的作

android -------- WIFI

mov 取ip地址 fico alt b- else if 無線網 pan PC 今天簡單的來聊一下安卓開發中的Wifi,一些常用的基礎,主要分為兩部分: 1:WiFi的信息 2:WiFi的搜索和連接 現在app大多都需要從網絡上獲得數據。所以訪問網絡是在

超詳細java中 大發彩_票平臺搭建 的ClassLoader

his sco string 配置環境變量 javac 選項 handle getc java開發 ClassLoader翻譯過來就是類加載器,普通的java開發者其實用到的不多,但對於某些框架開發者來說卻非常常見。理解ClassLoader的加載機制,也有利於我們編寫出更

Android Permission

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android ViewModel

1. ViewModel概述 2. 實現一個ViewModel 3. ViewModel的生命週期 4. 在fragments之間共享資料 5. ViewModel替換Loaders 6. 附加資源 1.

Android LiveData

官方文件翻譯 1.LiveData概述 1.1 使用LiveData的優點 1.2 使用LiveData物件 1.2.1 建立LiveData物件 1.2.2 觀察LiveData物件

Android Lifecycle(一)

官方文件翻譯 使用生命週期感知元件處理生命週期 Lifecycle Event State LifecycleOwner 實現一個自定義的LifecycleOwner 生命週期感

Android Animation

關於動畫的實現,Android提供了Animation,在Android SDK介紹了2種Animation模式: 1. Tween Animation:通過對場景裡的物件不斷做影象變換(平移、縮放、旋轉)產生動畫效果,即是一種漸變動畫; 2. Frame Animation:

Android開發之onTouch和onClick

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android UI之顏色資源的使用

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android開發--ContentProvider/Cursor的使用

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android Activity

生命週期 如上圖所示,Activity生命週期很簡單共七個生命週期函式,oncreate(),onrestart(),onstart(),onresume(),onpause(),onstop(),ondestroy(); 下面舉兩個例子來說明Activity生命週期函式呼叫關係。

Android Handler

Handler適用於執行緒間互動的一種機制。牽扯到四個類:Handler,Looper,MessageQueue,Message。 這四個類關係如下圖所示: 這個圖自己畫的,比較簡易,但是很能說明他們的關係 Handler:用於執行緒之間傳送訊息,一般Handler在主執行緒中被建

Eclipse整合Android NDK

1        目錄 Eclipse整合Android NDK說明... 1 2       為什麼要用NDK?... 2 3 &nbs

Android-Application

Preface 在學習一個SDK的時候,遇到了Application類的相關知識,其實之前也有學習過Application類的一些知識,但是日常開發中使用頻率不高,忘得差不多了.現在重新來總結下Application的使用 英語基礎好的可以去參考官方文件 官方文件 下面是官網對Application類

一看你就懂,超詳細 java 中的 ClassLoader

繼續 inter utils 普通 原來 handle 思考 還需 ear ClassLoader翻譯過來就是類加載器,普通的java開發者其實用到的不多,但對於某些框架開發者來說卻非常常見。理解ClassLoader的加載機制,也有利於我們編寫出更高效的代碼。ClassL

Android RecyclerView RecyclerView的動畫實現(移除、新增、改變、移動)和自定義動畫的實現

一丶新增刪除時候的重新整理問題 先上一下效果圖吧 1.為了方便起見我們還是先新增三個按鈕分別實現新增刪除和改變 2.在Adapter中寫呼叫方法並進行重新整理 public void remove(int position){ list.re

android Audio ( 二 )

android Audio 詳解( 二 ) 2018年01月04日 15:57:45 韓半仙 閱讀數:302更多 個人分類: linux驅動 2  tinyalsa    tinyalsa是Google在Android 4.0之