我目前正在开发一个分布式系统,其节点能够从服务器下载jar和dex文件,以便在运行时更改其行为。 Not-Android节点使用以下代码添加jar来调用ClassLoader提供的addURL方法:
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) { }
我知道执行动态代码卸载时的安全问题,但这只是一个研究项目。
答案 0 :(得分:1)
尝试https://gist.github.com/nickcaballero/7045993
中的代码此方法将新创建的DexClassLoader附加到现有的DexClassLoader。
请注意它使用反射,因此它可能不适用于所有Android版本。至少它适用于我的SDK19。