dex文件的热修复方法有很多,例如通过类加载器或者偏底层的实现通过修改ArtMethod。这里只分析基于类加载器的dex热修复原理,实际dex插件化的原理和热修复的原理也有类似之处。
dex热修复原理
android虚拟机中每一个classloader类加载器都有一个对应的DexPathList类,而DexPathList类有一个对应的Elements数组,Elements数组中保存了此classloader类加载器加载的所有dex文件信息,dex文件信息用一个DexFile类来描述。
DexFile中保存了加载的dex文件信息,其中包含了此dex文件包含的所有类名称,在通过主动调用脱函数抽取类壳的时候就是通过枚举apk中所有的类加载器并通过反射最后得到所有加载dex文件对应的DexFile,通过DexFile进一步获取到所有的类名称通过classloader类加载器调用loadclass主动加载(显式加载)此类从而使被抽取的函数代码进行回填。
function dealwithClassLoader(classloaderobj) {
if (Java.available) {
Java.perform(function () {
try {
var dexfileclass = Java.use("dalvik.system.DexFile");
var BaseDexClassLoaderclass = Java.use("dalvik.system.BaseDexClassLoader");
var DexPathListclass = Java.use("dalvik.system.DexPathList");
var Elementclass = Java.use("dalvik.system.DexPathList$Element");
var basedexclassloaderobj = Java.cast(classloaderobj, BaseDexClassLoaderclass);
var tmpobj = basedexclassloaderobj.pathList.value;
var pathlistobj = Java.cast(tmpobj, DexPathListclass);
var dexElementsobj = pathlistobj.dexElements.value;
if (dexElementsobj != null) {
for (var i in dexElementsobj) {
var obj = dexElementsobj[i];
var elementobj = Java.cast(obj, Elementclass);
tmpobj = elementobj.dexFile.value;
var dexfileobj = Java.cast(tmpobj, dexfileclass);
const enumeratorClassNames = dexfileobj.entries();
while (enumeratorClassNames.hasMoreElements()) {
var className = enumeratorClassNames.nextElement().toString();
if(-1 != className.indexOf("com.reverccqin")){
console.log("start loadclass->", className);
var loadclass = classloaderobj.loadClass(className);
console.log("after loadclass->", loadclass);
}
}
}
}
} catch (e) {
console.log(e)
}
});
}
}
对于基于类加载器的dex热修复而言,其通过动态下发更新的dex文件并通过自定义的类加载器加载此dex文件。然后通过反射获取到默认classloader和自定义classloader中待更新dex文件对应的Element,将默认classloader的Element替换位自定义classloader的Element即可实现热修复。
这样的之后显式/隐式加载类的行为都会从热修复后的Element中得到对应的类信息并进行调用执行,热修复实现了不必要更新应用程序在程序运行时修改程序执行逻辑。
标签:dex,Java,修复,classloader,var,加载 From: https://www.cnblogs.com/revercc/p/17022213.html