我们使用自定义MyClassLoader
扩展ClassLoader
来替换默认PathClassLoader
,例如:
Context mBase = (Context) getFieldValue(application, "mBase");
Object mPackageInfo = getFieldValue(mBase, "mPackageInfo");
ORIGINAL_CLASS_LOADER = (ClassLoader) getFieldValue(mPackageInfo, "mClassLoader");
CUSTOMED_CLASS_LOADER = new MyClassLoader(ORIGINAL_CLASS_LOADER);
当应用程序处于onCreat时执行。
第一个问题是,并非所有类都由MyClassLoader
首先加载,只有MyActivitys
而MyViews
由MyClassLoader
加载,MyFragments
仍在加载按PathClassLoader
。这与Context有什么关系吗?
在MyClassLoader
我们按
public Class<?> loadClass(String className)
throws ClassNotFoundException {
try {
ClassLoader myDexClassLoader = loaders.get("DEX");
if(myDexClassLoader != null){
Class<?> c = null;
try {
c = myDexClassLoader.loadClass(className);
// c = loader.findClass(className);
} catch (ClassNotFoundException e) {
}
if (c != null) {
return c;
}
}
}
return super.loadClass(className);
}`
和 myDexClassLoader 定义为
public static class MyDexClassLoader extends DexClassLoader {
public MyDexClassLoader(String dexPath, String dexOutputDir,
String libPath, ClassLoader parent) {
super(dexPath, dexOutputDir, libPath, parent);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name);
}
@SuppressLint("NewApi")
@Override
public Class<?> loadClass(String className)
throws ClassNotFoundException {
Class<?> clazz = null;
try {
clazz = findClass(className);
} catch (ClassNotFoundException e) {
}
if (clazz != null) {
return clazz;
}
return super.loadClass(className);
}
}
MyDexClassLoader
与PatchDex文件一起包含 A1 和 C1 等类。
PathClassLoader
是MyDexClassLoader
和MyClassLoader
的父母。
在OriginalApk中,我们有原始类 A1 B1 C1 。
第二个问题是,我们可以使用loadClass
方法打印,MyDexClassLoader
由MyClassLoader
(由MyDexClassLoader
调用)从PatchDex加载新A1 ,
但由于 B1 类不在PatchDex中,MyClassLoader
(为什么不首先由PathClassLoader
调用)最终使用它的父(MyDexClassLoader
)来加载旧B1 ,
B1类直接使用C1,所以我们必须加载C1类。通过print loadClass方法,我们发现PathClassLoader
已经取得了控制权,但没有使用它的PatchDex,只使用了父MyDexClassLoader
的旧C1 。
这是怎么发生的?为什么setUp
直接由它的父级加载C1类,但是当它有PatchDex时它不是?
提前致谢。
答案 0 :(得分:1)
例如,pathclassloader和dexclassloader不再引用child。这些类加载器有自己的dex文件列表,用于从已注册的dex文件加载类。
所以,不要先使用超类。 必须首先从您自己的自定义类加载器中找到类。