【问题标题】:DexClassLoader, reload Code fails with Signal 7DexClassLoader,重新加载代码失败,信号 7
【发布时间】:2014-12-04 16:49:56
【问题描述】:

我正在尝试构建一个插件系统,其中 DexClassLoader 正在从其他已安装的包含片段(我的插件)的 apk 中获取代码,并将它们显示在我的主机中。这工作得很好。

我也喜欢使插件可热插拔,这意味着我可以更改插件的代码,安装新的,主机会注意到并加载新代码。如果我是第一次更改代码,这也有效。 (虽然我认为不应该,但似乎我对这段代码的理解有误:

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

)

如果我再次尝试使用相同的插件,主机会在requiredClass = classLoader.loadClass(fullName); 关闭,类似

libc 致命信号 7 (SIGBUS) 位于 0x596ed4d6 (code=2),线程 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;
    }

非常感谢!

【问题讨论】:

    标签: android plugins classloader dexclassloader


    【解决方案1】:

    这并不重要(因为实际上没有人查看此内容),或者我什至了解发生了什么,但是在重新加载之前删除dexTemp.getAbsolutePath() 中插件的相应文件可以解决问题。

    PS:风滚草徽章,耶!

    【讨论】:

    • 如果您要提取的 apk/zip 名为“myapp.apk”,则在DexClassLoader 提取它的缓存目录中将有一个“myapp.dex”文件。在为新的 apk/zip 创建新的 DexClassLoader 之前删除该文件,它确实应该可以工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    • 2014-02-02
    • 2018-05-21
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多