运行时将dex添加到Android类路径

3

我目前正在开发一个分布式系统,其节点能够从服务器下载JAR和DEX文件,以在运行时更改其行为。非安卓节点使用以下代码来调用ClassLoader提供的addURL方法来添加JAR:

File f = new File(fileName);
URL u = f.toURI().toURL();

URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();

Class<?> sysclass = URLClassLoader.class;

try {
    Method method = sysclass.getDeclaredMethod("addURL", parameters);
    method.setAccessible(true);
    method.invoke(sysloader, new Object[] { u });
} catch (Throwable t) { }

在Android节点上,是否可以使用dex文件进行相同的操作?DexClassLoader和PathClassLoader没有提供addURL这样的方法。我知道可以使用反射添加单个类,但是我不知道如何添加整个dex文件。问题在于,如果我逐个添加dex中的所有类,那么由于一个类可能依赖于另一个尚未添加的类,我会收到缺少依赖项的异常。无论如何,我用来添加单个类的代码如下。

File f = new File(pathToSaveFile + dexFile);
Object obj = null;
final File optimizedDexOutputPath = context.getDir("outdex", 0);

DexClassLoader classLoader = new DexClassLoader(
    f.getAbsolutePath(),
    optimizedDexOutputPath.getAbsolutePath(), null,
    context.getClassLoader());

String path = pathToSaveFile + dexFile;

try {
    DexFile dx = DexFile.loadDex(
        path,
        File.createTempFile("opt", "dex", context.getCacheDir()).getPath(),
        0);
    Class<?> myClass = classLoader.loadClass(className);
} catch (Exception e) { }

我知道在执行动态代码卸载时存在安全问题,但这只是一个研究项目。

1个回答

1

https://gist.github.com/nickcaballero/7045993中尝试代码。

这种方法将新创建的DexClassLoader附加到现有的类加载器上。

请注意,它使用反射,因此可能无法适用于所有Android版本。至少在我的SDK19上可以工作。


很高兴能帮到你。一段时间过去了,现在谷歌已经为多dex提供了官方支持(主要是为了绕过众所周知的65k方法限制)。您可以参考https://github.com/casidiablo/multidex获取详细信息。这段代码可能涵盖更多的API版本。 - weidongxu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接