Android類載入器

來源:互聯網
上載者:User

標籤:

郭嘉
郵箱:[email protected]
部落格:http://blog.csdn.net/allenwells
github:https://github.com/AllenWell

在介紹Android的類載入機制之前,我們需要先瞭解一下Java的類載入機制。

【Java 安全技術探索之路系列:J2SE安全架構】之五:類載入器

一 Dalvik虛擬機器與Java虛擬機器

Dalvik虛擬機器如同其他Java虛擬機器一樣,在運行程式時首先需要將對應的類載入到記憶體中。而在Java標準的虛擬機器中,類載入可以從class檔案中讀取,也可以是其他形式的二進位流。因此,我們常常利用這一點,在程式運行時手動載入Class,從而達到代碼動態載入執行的目的。

然而Dalvik虛擬機器畢竟不算是標準的Java虛擬機器,因此在類載入機制上,它們有相同的地方,也有不同之處。我們必須區別對待。例如,在使用標準Java虛擬機器時,我們經常自訂繼承自ClassLoader的類載入器。然後通過defineClass方法來從一個二進位流中載入Class。然而,這在Android裡是行不通的,

二 Android類載入器

Android的類載入器主要有兩個PathClassLoader和DexClassLoader,其中PathClassLoader是預設的類載入器,下面我們就來說說兩者的區別與聯絡。

  • PathClassLoader:支援載入DEX或者已經安裝的APK(因為存在緩衝的DEX)。
  • DexClassLoader:支援載入APK、DEX和JAR。

DexClassLoader和PathClassLoader都屬於符合雙親委派模型的類載入器(因為它們沒有重載loadClass方法)。也就是說,它們在載入一個類之前,回去檢查自己以及自己以上的類載入器是否已經載入了這個類。如果已經載入過了,就會直接將之返回,而不會重複載入。

無論是PathClassLoader還是DexClassLoader都是繼承於BaseClassLoader,那麼我們就先來看一下BaseCLassLoader的實現。

2.1 BaseClassLoader

【android-21】BaseDexClassLoader的源碼如下所示:

package dalvik.system;import java.io.File;import java.net.URL;import java.util.Enumeration;public class BaseDexClassLoader  extends ClassLoader{  public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent)  {    throw new RuntimeException("Stub!");  }  protected Class<?> findClass(String name)    throws ClassNotFoundException  {    throw new RuntimeException("Stub!");  }  protected URL findResource(String name)  {    throw new RuntimeException("Stub!");  }  protected Enumeration<URL> findResources(String name)  {    throw new RuntimeException("Stub!");  }  public String findLibrary(String name)  {    throw new RuntimeException("Stub!");  }  protected synchronized Package getPackage(String name)  {    throw new RuntimeException("Stub!");  }  public String toString()  {    throw new RuntimeException("Stub!");  }}
2.2 PathClassLoader

【android-21】PathClassLoader的源碼如下所示:

package dalvik.system;import java.io.File;public class PathClassLoader  extends BaseDexClassLoader{  public PathClassLoader(String dexPath, ClassLoader parent)  {    super((String)null, (File)null, (String)null, (ClassLoader)null);throw new RuntimeException("Stub!");  }  public PathClassLoader(String dexPath, String libraryPath, ClassLoader parent)  {    super((String)null, (File)null, (String)null, (ClassLoader)null);throw new RuntimeException("Stub!");  }}

從源碼可以看出,PathClassLoader有兩個建構函式,函數中的參數含義如下所示:

  • String dexPath:載入APK、DEX和JAR的路徑。
  • String libraryPath:載入DEX的時候需要用到的lib庫,libraryPath一般包括/vendor/lib和/system/lib。
  • ClassLoader parent:DEXClassLoader指定的父類載入器

PathClassLoader

2.3 DexClassLoader

【android-21】DexClassLoader的源碼如下所示:

package dalvik.system;import java.io.File;public class DexClassLoader  extends BaseDexClassLoader{  public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)  {    super((String)null, (File)null, (String)null, (ClassLoader)null);throw new RuntimeException("Stub!");  }}

從源碼可以看出,DexClassLoader只有一個建構函式,該函數中的參數含義如下所示:

  • String dexPath:載入APK、DEX和JAR的路徑。
  • String optimizedDirectory:是DEX的輸出路徑。
  • String libraryPath:載入DEX的時候需要用到的lib庫,libraryPath一般包括/vendor/lib和/system/lib。
  • ClassLoader parent:DEXClassLoader指定的父類載入器

大家可以發現DexClassLoader的建構函式比PathClassLoader多了一個String optimizedDirectory參數,這是因為PathClassLoader是載入/data/app中的APK,而這部分的APK都會解壓釋放dex到指定的目錄。

2.4 DexFile

DexClassLoader和PathClassLoader其實都是通過DexFile這個類來實作類別載入的。這裡需要順便提一下的是,Dalvik虛擬機器識別的是dex檔案,而不是class檔案。因此,我們供類載入的檔案也只能是dex檔案,或者包含有dex檔案的.apk或.jar檔案。

也許有人想到,既然DexFile可以直接載入類,那麼我們為什麼還要使用ClassLoader的子類呢?DexFile在載入類時,具體是調用成員方法loadClass或者loadClassBinaryName。其中loadClassBinaryName需要將包含包名的類名中的”.”轉換為”/”。我們看一下loadClass代碼就清楚了。

【android-21】DexFile源碼如下所示:

package dalvik.system;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.util.Enumeration;public final class DexFile{  public DexFile(File file)    throws IOException  {    throw new RuntimeException("Stub!");  }  public DexFile(String fileName)    throws IOException  {    throw new RuntimeException("Stub!");  }  public static DexFile loadDex(String sourcePathName, String outputPathName, int flags)    throws IOException  {    throw new RuntimeException("Stub!");  }  public String getName()  {    throw new RuntimeException("Stub!");  }  public String toString()  {    throw new RuntimeException("Stub!");  }  public void close()    throws IOException  {    throw new RuntimeException("Stub!");  }  public Class loadClass(String name, ClassLoader loader)  {    throw new RuntimeException("Stub!");  }  public Enumeration<String> entries()  {    throw new RuntimeException("Stub!");  }  protected void finalize()    throws Throwable  {    throw new RuntimeException("Stub!");  }  public static native boolean isDexOptNeeded(String paramString)    throws FileNotFoundException, IOException;}
三 Android類載入機制3.1類載入器結構3.1.1 系統類別載入器

舉例

Context.class.getClassLoader();

上述代碼得到的結果表明系統類別的載入器是BootClassLoader。

ClassLoader.getSystemClassLoader().getParent();

上述代碼錶明系統載入器的父類載入器還是

3.2.2 應用程式載入器

舉例

getClassLoader();

上述代碼得到的結果表明應用程式的載入器是PathClassLoader

getClassLoader().getParent();

上述代碼得到的結果表明應用程式的家在啟動餓父類載入器是BootClassLoader。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android類載入器

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.