Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 關於Android的ClassLoader探索

關於Android的ClassLoader探索

編輯:Android開發實例

    最近突發奇想,想做一個插件框架,就是實現一個微內核,所有擴展功能都通過下載插件加載的方式來實現,原理跟現在用的eclipse差不多。要做到這些動態加載類少不了,就是內核上事先定義好接口,通過網絡或其他方式下載的插件要實現這些接口,只要定義好規則,系統就可以使用這些插件了。

    Android動態加載不是程序本身的類,要用到PathClassLoader和DexClassLoader, 兩個類的構造方法分別是:

  1. PathClassLoader(String path, ClassLoader parent);  
  2. DexClassLoader(String dexPath, String dexOutputDir, String libPath, ClassLoader parent); 

 

     網上查了一下資料,PathClassLoader的類加載路徑必須在/data/app路徑下。DexClassLoader可以加載sdcard目錄下的apk或jar文件,編譯好的類不能立即使用,要通過dx工具轉換為.dex格式的。一切實驗都很順利,但到類型轉換這步出錯了,代碼如下:

  1. DexClassLoader loader = new DexClassLoader("/sdcard/dog.apk", "/sdcard", null, ClassLoader.getSystemClassLoader());  
  2. Class<?> clazz =  loader.loadClass("czh.plugin.Dog");  
  3. Animal dog = (Animal)clazz.newInstance();     
  4. dog.sayHello();  

 

    上述代碼中類Dog繼承自類Animal,執行這些代碼的apk定義了Animal,但Dog是在dog.apk定義的,dog.apk裡面也定義了Animal。問題就出來了,在clazz實例化一個對象想轉換為Animal時,程序報了ClassCastException異常。想了一下,實例化的Dog對象應該只認識dog.apk裡的Animal類是它的父類,而認為執行上述代碼的apk裡Animal類不是它的父類。於是俺把dog.apk裡的Animal類去掉,重新用dx打包放到sdcard目錄下,結果這次報了不能找到類czh.plugin.Dog的異常,也就是無法加載類Dog。

     查看了Class類forName(String name)方法的源代碼,發現它們加載類用的不是ClassLoader.getSystemClassLoader(), 而是VMStack.getCallingClassLoader(), 於是俺把代碼改了一番,終於運行通過了:

  1. DexClassLoader loader = new DexClassLoader("/sdcard/dog.apk", "/sdcard", null, VMStack.getCallingClassLoader()); 

    Java的ClassLoader其實是一個鏈式結構,加載類的時候優先從最頂層的ClassLoader開始加載,若無法找到該類才嘗試下一級ClassLoader加載。上述代碼保證了類Animal能被VMStack.getCallingClassLoader()加載,類Dog被loader加載,同時這兩個類在同一個ClassLoader加載鏈中,確保了它們的父子關系能正常識別,這樣就不會發生ClassCastException異常了。

     不過VMStack這個類被標識為deprecated, 將來可能被google去除不給我們使用,到時候就要想些方法來克服這點困難了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved