我正在使用DexClassLoader进行一些测试,看看它是否可以更新"我的应用程序具有新功能。目前我已经有了这种测试方法,它可以与testClass一起运行并运行test()方法。我想知道的是,我怎样才能更换"或者"更新"已经存在的班级..?欢迎任何想法或其他建议。
方法:
public static void loadExtLib(String pathDexFile, Context ctx) {
String temp = ctx.getDir("temp", 0).toString();
DexClassLoader classLoader = new DexClassLoader(pathDexFile,
temp, null, ctx.getClass().getClassLoader());
String testClass = "com.mystudio.myapp.TestClass";
Class<?> libProviderClass = null;
try {
libProviderClass = classLoader.loadClass(testClass);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
try {
Method m = libProviderClass.getDeclaredMethod("test", null);
try {
m.invoke(libProviderClass, null);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
Log.v("loadClass", "loaded: " + testClass);
}
答案 0 :(得分:4)
一般不能“替换”或“更新”课程;只有DexClassLoader
或其中一个子加载器加载的类才能看到加载的类。例如,您不能将java.lang.String
替换为可以绕过类中安全限制的恶意版本。
这有点降低了使用相同名称加载多个类的实用程序。另一方面,它确保类加载器A的动作独立于类加载器B的动作,只要一个不是另一个的父类。
使用运行时加载类的一种可能有用的方法是在基本加载器中定义一个接口,该接口由类的“旧”和“新”版本实现。通过接口引用类的实例,可以避免“旧”代码无法看到“新”类定义的事实。
(考虑这个问题的最好方法是用类加载器精神标记每个类。然后很明显,你不能将String'new
传递给为String'old
编写的函数,但如果它们两者都实现CharSequence'old
然后你总是可以通过它来引用它们。)
Dalvik测试中有一些代码可以执行运行时“替换”,并且可能对读取有用。请参阅068-classloader测试。 src
和src-ex
的内容构建在单独的.jar文件中;后者在运行时加载。