返回

插件化的新方式把插件apk的elementsField添加到系统的BaseDexClassLoader中去

发布时间:2022-11-30 07:37:57 179

模板代码

String cachePath = context.getCacheDir().getAbsolutePath();
String apkPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/plugin.apk";
DexClassLoader dexClassLoader = new DexClassLoader(apkPath, cachePath, cachePath, context.getClassLoader());

// 第一步 找到 插件的Elements数组 dexPathlist ----?dexElement

try {
Class myDexClazzLoader=Class.forName("dalvik.system.BaseDexClassLoader");
Field myPathListFiled=myDexClazzLoader.getDeclaredField("pathList");
myPathListFiled.setAccessible(true);
Object myPathListObject =myPathListFiled.get(dexClassLoader);


Class myPathClazz=myPathListObject.getClass();
Field myElementsField = myPathClazz.getDeclaredField("dexElements");
myElementsField.setAccessible(true);
// 自己插件的 dexElements[]
Object myElements=myElementsField.get(myPathListObject);

// 第二步 找到 系统的Elements数组 dexElements
PathClassLoader pathClassLoader= (PathClassLoader) context.getClassLoader();
Class baseDexClazzLoader = Class.forName("dalvik.system.BaseDexClassLoader");
Field pathListFiled = baseDexClazzLoader.getDeclaredField("pathList");
pathListFiled.setAccessible(true);
Object pathListObject = pathListFiled.get(pathClassLoader);

Class systemPathClazz = pathListObject.getClass();
Field systemElementsField = systemPathClazz.getDeclaredField("dexElements");
systemElementsField.setAccessible(true);
//系统的 dexElements[]
Object systemElements = systemElementsField.get(pathListObject);
// 第三步 上面的dexElements 数组 合并成新的 dexElements 然后通过反射重新注入系统的Field (dexElements )变量中

// 新的 Element[] 对象
// dalvik.system.Element

int systemLength = Array.getLength(systemElements);
int myLength = Array.getLength(myElements);
// 找到 Element 的Class类型 数组 每一个成员的类型
Class<?> sigleElementClazz = systemElements.getClass().getComponentType();
int newSysteLength = myLength + systemLength;
Object newElementsArray=Array.newInstance(sigleElementClazz, newSysteLength);
//融合
for (int i = 0; i < newSysteLength; i++) {
// 先融合 插件的Elements
if (i < myLength) {
Array.set(newElementsArray, i, Array.get(myElements, i));
}else {
Object value = Array.get(systemElements, i - myLength);
Array.set(newElementsArray,i, value);
}
}
Field elementsField=pathListObject.getClass().getDeclaredField("dexElements");;
elementsField.setAccessible(true);
// 将新生成的EleMents数组对象重新放到系统中去
elementsField.set( pathListObject,newElementsArray);


} catch (Exception e) {
e.printStackTrace();
}

这样的方式就实现了class不需要​​class.forname()​​指定插件classloader了。这种方式弊端就是我这个qq机器人是不能这么搞的,插件卸载了我还要手动移除。。。

多累啊。

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线