使用补丁包中的方法信息进行替换
1.在 Java 层获取 补丁包方法的信息
通过 DexFile 获取到补丁包中的方法对象。
public class DexManager {
private static final String TAG = "DexManager";
private static final DexManager ourInstance = new DexManager();
public static DexManager getInstance() {
return ourInstance;
}
private DexManager() {
}
private Context mContext;
public void setContext(Context context) {
this.mContext = context;
}
public void loadDex(File file) {
try {
DexFile dexFile = DexFile.loadDex(file.getAbsolutePath(),
new File(mContext.getCacheDir(), "opt").getAbsolutePath(),
Context.MODE_PRIVATE);
Enumeration<String> entries = dexFile.entries();
while (entries.hasMoreElements()) {
String className = entries.nextElement();
// Class.forName(className);//为什么不能用这种方式?这种方式只能获取安装app中的class
Class fixClazz = dexFile.loadClass(className, mContext.getClassLoader());
if (fixClazz != null) {
fixClass(fixClazz);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void fixClass(Class fixClazz) {
Method[] methods = fixClazz.getDeclaredMethods();
// Method[] methods = fixClazz.getMethods();
MethodReplace methodReplace;
String className;
String methodName;
Class<?> bugClass;
Method bugMethod;
for (Method fixMethod : methods) {
methodReplace = fixMethod.getAnnotation(MethodReplace.class);
if (methodReplace == null) {
continue;
}
Log.e(TAG, "找到修复好的方法: " + fixMethod.getDeclaringClass() + "@" + fixMethod.getName());
className = methodReplace.className();
methodName = methodReplace.methodName();
if (!TextUtils.isEmpty(className) && !TextUtils.isEmpty(methodName)) {
try {
bugClass = Class.forName(className);
bugMethod =
bugClass.getDeclaredMethod(methodName, fixMethod.getParameterTypes());
replace(bugMethod, fixMethod);
Log.e(TAG, "修复完成!");
} catch (Exception e) {
e.printStackTrace();
}
}else {
Log.e(TAG, "/修复好的方法未设置自定义注解属性");
}
}
}
private native void replace(Method bugMethod, Method fixMethod);
static {
System.loadLibrary("native-lib");
}
}
2.使用补丁包中的方法信息替换
#include <jni.h>
#include <string>
#include <android/log.h>
#include "art_5_1.h"
extern "C"
JNIEXPORT void JNICALL
Java_com_netease_andfix_DexManager_replace(JNIEnv *env, jobject instance, jobject bugMethod,
jobject fixMethod) {
env->FindClass()
//ba获得指向被替换的目标方法的指针(有bug的方法的指针)
art::mirror::ArtMethod *bugArtMethod = reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(
bugMethod));
//获得指向新的方法的指针(被修复了的方法的指针)
art::mirror::ArtMethod *fixArtMethod = reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(
fixMethod));
reinterpret_cast<art::mirror::Class *>(fixArtMethod->declaring_class_)->class_loader_ =
reinterpret_cast<art::mirror::Class *>(bugArtMethod->declaring_class_)->class_loader_; //for plugin classloader
reinterpret_cast<art::mirror::Class *>(fixArtMethod->declaring_class_)->clinit_thread_id_ =
reinterpret_cast<art::mirror::Class *>(bugArtMethod->declaring_class_)->clinit_thread_id_;
reinterpret_cast<art::mirror::Class *>(fixArtMethod->declaring_class_)->status_ =
reinterpret_cast<art::mirror::Class *>(bugArtMethod->declaring_class_)->status_ - 1;
reinterpret_cast<art::mirror::Class *>(fixArtMethod->declaring_class_)->super_class_ = 0;
//把就函数的成员变量替换为新函数的
bugArtMethod->declaring_class_ = fixArtMethod->declaring_class_;
bugArtMethod->dex_cache_resolved_methods_ = fixArtMethod->dex_cache_resolved_methods_;
bugArtMethod->access_flags_ = fixArtMethod->access_flags_;
bugArtMethod->dex_cache_resolved_types_ = fixArtMethod->dex_cache_resolved_types_;
bugArtMethod->dex_code_item_offset_ = fixArtMethod->dex_code_item_offset_;
bugArtMethod->method_index_ = fixArtMethod->method_index_;
bugArtMethod->dex_method_index_ = fixArtMethod->dex_method_index_;
bugArtMethod->ptr_sized_fields_.entry_point_from_interpreter_ = fixArtMethod->ptr_sized_fields_.entry_point_from_interpreter_;
bugArtMethod->ptr_sized_fields_.entry_point_from_jni_ = fixArtMethod->ptr_sized_fields_.entry_point_from_jni_;
bugArtMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = fixArtMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_;
__android_log_print(ANDROID_LOG_ERROR, "AndFix","replace_5_1: %d , %d",
static_cast<const char *>(bugArtMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_),
fixArtMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_);
}
网友评论