正常开发流程
热修复开发流程
当线上的项目出现问题了,需要重新发布版本解决bug,重新发新版本apk;
但是随着技术不断的更新,线上项目出现bug,可以通过热修复,在不需要发布新版本的情况下进行bug的修复。
Andfix采用native底层替换
Android代码中的每个method在art虚拟机中都有一个ArtMethod结构体指针与其对应。
在Android中一个方法在art中对应一个ArtMethod,ArtMethod中保存着方法的 类、访问权限和执行地址等信息。
也就说虚拟机就是通过ArtMethod结构体来操作java方法。
源码位置:
/art/runtime/art_method.h
ArtMethod结构:
class ArtMethod中成员变量
class ArtMethod FINAL {
...
protected:
GcRoot declaring_class_;
std::atomic access_flags_;
// Offset to the CodeItem.
uint32_t dex_code_item_offset_;
// Index into method_ids of the dex file associated with this method.
uint32_t dex_method_index_;
uint16_t method_index_;
uint16_t hotness_count_;
struct PtrSizedFields {
// Depending on the method type, the data is
// - native method: pointer to the JNI function registered to this method
// or a function to resolve the JNI function,
// - conflict method: ImtConflictTable,
// - abstract/interface method: the single-implementation if any,
// - proxy method: the original interface method or constructor,
// - other methods: the profiling data.
void* data_;
// Method dispatch from quick compiled code invokes this pointer which may cause bridging into
// the interpreter.
void* entry_point_from_quick_compiled_code_;
} ptr_sized_fields_;
...
bug类代码:
package com.example.andfix;
import android.content.Context;
public class Worker {
public void work(Context context) {
throw new RuntimeException("今天不搬砖!");
}
}
修复的类代码:
package com.example.andfix.web;
import android.content.Context;
import android.widget.Toast;
public class Worker {
public void work(Context context){
Toast.makeText(context, "今天又是搬砖的一天。", Toast.LENGTH_SHORT).show();;
}
}
替换底层ArtMethod结构体
demo直接使用修复的类底层替换有bug类的方法;
实际项目中从服务器下载dex到手机本地,加载dex找到要修复的bug类进行方法的替换。
总结
不管使用的是art虚拟机还是dalvik虚拟机,实现热修复的关键是在底层进行method的指针的替换,将出现bug的method的指针替换到修复后的method的指针。
每个android版本 ArtMethod结构体内容不同,需要做兼容。
demo基于Android 9.0
>>> 源码下载



