2014-12-04 28 views
1

我試圖建立一個插件系統,其中DexClassLoader從其他已安裝的包含碎片(我的插件)的apks獲取代碼,並在我的主機中顯示它們。這工作很好。DexClassLoader,重新加載代碼失敗,Signal 7

我也喜歡使插件hotswappable,這意味着我可以從插件更改代碼,安裝新的和主機會注意到並將加載新的代碼。如果我第一次更改代碼,這也適用。 (雖然我認爲它不應該,似乎我有這個代碼的一個錯誤的認識:

try { 
requiredClass = Class.forName(fullName); 
} catch(ClassNotFoundException e) { 
isLoaded = false; 
} 

,如果我用同樣的插件,主機嘗試它第二次在requiredClass = classLoader.loadClass(fullName);關閉與0x596ed4d6(代碼= 2)類似

libc的致命信號7(SIGBUS),螺紋28814 (ctivityapp.host)

有沒有人對DexClassLoader的功能有更深入的瞭解,並告訴我,這裏發生了什麼?我很堅持這一點。

繼承人的方法的完整的代碼加載外部代碼:

 /** 
    * takes the name of a package as String, and tries to load the code from the corresponding akp using DexclassLaoder. 
    * Checking if a package is a valid plugin must be done before calling this. 
    * The Plugin must contain a public class UI that extends Fragment and implements plugin as a starting point for loading 
    * @param packageName The full name of the package, as String 
    * @return the plugins object if loaded, null otherwise 
    */ 
    private Plugin attachPluginToHost(String packageName) { 
     try { 
      Class<?> requiredClass = null; 
      final ApplicationInfo info = context.getPackageManager().getApplicationInfo(packageName,0); 
      final String apkPath = info.sourceDir; 
      final File dexTemp = context.getDir("temp_folder", 0); 
      final String fullName = packageName + ".UI"; 
      boolean isLoaded = true; 
      // Check if class loaded 
      try { 
       requiredClass = Class.forName(fullName); 
      } catch(ClassNotFoundException e) { 
       isLoaded = false; 
      } 
      if (!isLoaded) { 
       final DexClassLoader classLoader = new DexClassLoader(apkPath, dexTemp.getAbsolutePath(), null, context.getApplicationContext().getClassLoader()); 
       requiredClass = classLoader.loadClass(fullName); 
      } 
      if (null != requiredClass) { 
       // Try to cast to required interface to ensure that it's can be cast 
       final Plugin plugin = Plugin.class.cast(requiredClass.newInstance()); 
       installedPlugins.put(plugin.getName(), plugin); 
       return plugin; 
      } 
      } catch (PackageManager.NameNotFoundException e) { 
       e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
       e.printStackTrace(); 
      } catch (InstantiationException e) { 
       e.printStackTrace(); 
      } catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } 
      return null; 
    } 

提前非常感謝!

回答

1

不是真的很重要(因爲沒有人真的看到這個),或者我甚至明白髮生了什麼,但在重新加載之前刪除dexTemp.getAbsolutePath()中插件的相應文件解決了問題。

PS:Tumbleweed-Badge,YAY!

+0

如果您正在提取的apk/zip稱爲「myapp.apk」,則在DexClassLoader提取它的緩存目錄中會有一個「myapp.dex」文件。在爲新的apk/zip創建一個新的'DexClassLoader'之前刪除該文件,它確實可以工作。 – Dauntless 2016-01-26 08:40:58