美文网首页
即时生效热修复

即时生效热修复

作者: WaterYuan | 来源:发表于2019-06-29 17:09 被阅读0次

一、微信

tinker热修复 使用 framework java
核心:在加载bug的dex文件加载补丁dex文件

现有apk里有dex1、dex2两个文件,
假设dex1中某个类ClassA某个方法中有bug需紧急热修复,
服务端将修复好的类打包成dex3文件,
那么客户端需要通过服务器下载dex3文件到手机并在加载dex1之前加载dex3
原理:加载了dex3中已修复的类ClassA后就不会再加载dex1中的带有bug的类ClassA

总结类替换


二、阿里云

github传送门
核心:通过jni方法替换出现bug的java代码中的method,方法的替换

修复步骤:

  1. 服务端生成补丁包dex文件(用注解标注要修改的类及方法)让用户下载
注解
  1. 客户端通过网络下载修复好的dex包
  2. 客户端加载修复好的dex包,通过反射注解定位到出bug的类及方法
  public void loadDex(File dexFilePath) {
        File optFile = new File(context.getCacheDir(), dexFilePath.getName());
        if (optFile.exists()) {
            optFile.delete();
        }
        try {
            // 加载dex,若dex在SD卡,则需要先申请SD的读写权限
            DexFile dexFile = DexFile.loadDex(dexFilePath.getAbsolutePath(), optFile.getAbsolutePath(), Context.MODE_PRIVATE);
            Enumeration<String> enumeration = dexFile.entries();
            while (enumeration.hasMoreElements()) {
                String className = enumeration.nextElement();
                Class realClazz = dexFile.loadClass(className, context.getClassLoader());
                Log.i(TAG, "loadDex: 找到类=" + className);
                fix(realClazz);
            }
        } catch (IOException e) {
            e.printStackTrace();
            /* java.io.IOException: No original dex files found for dex location /storage/emulated/0/_ae/fix.dex
             * 是缺少授予WRITE_EXTERNAL_STORAGE权限
             * */
        }
    }

    private void fix(Class realClazz) {
        Method[] declaredMethods = realClazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            Replace replace = method.getAnnotation(Replace.class);
            if (replace == null) {
                continue;
            }
            String wrongClazzName = replace.clazz();
            String wrongMethod1Name = replace.method();
            try {
                // TODO: 2019/6/29 混淆需要一些其它处理
                Class<?> wrongClazz = Class.forName(wrongClazzName);
                // 修复带参方法时,注意参数问题
                Method wrongMethod = wrongClazz.getMethod(wrongMethod1Name, method.getParameterTypes());
                replace(wrongMethod, method);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }

        }
    }
  1. 核心:通过JNI替换Java代码中出现bug的method
    参考 http://androidxref.com/9.0.0_r3/xref/art/runtime/art_method.h
    写一个自定义的头文件,名字随意,比如art.h,代码如下
//
// Created by yuan on 2019/6/29.
//
#include <cstdint>

#ifndef HOTFIX_ART_H
#define HOTFIX_ART_H
namespace art {
    class ArtMethod {
    public:
        uint32_t declaring_class_;
        uint32_t access_flags_;
        uint32_t dex_code_item_offset_;
        uint32_t dex_method_index_;
        uint16_t method_index_;
        uint16_t hotness_count_;
        struct PtrSizedFields {
            ArtMethod **dex_cache_resolved_methods_;
            uint32_t *dex_cache_resolved_types_;
            void *entry_point_from_jni_;
            void *entry_point_from_quick_compiled_code_;
        } ptr_sized_fields_;
    };
} // namespace art
#endif //HOTFIX_ART_H

自定义头文件只是声明,使如下代码通过编译,代码真正执行仍是依靠手机系统中的art_method.h

#include <jni.h>
#include <string>
#include "art.h"

extern "C" JNIEXPORT void JNICALL
Java_com_yuan_hotfix_andfix_DxManager_replaceJNI(JNIEnv *env, jobject instance, jobject wrongMethod,
                                                 jobject rightMethod) {
    art::ArtMethod *artReplaceMethod = (art::ArtMethod *) env->FromReflectedMethod(
            wrongMethod);
    art::ArtMethod *artMethod = (art::ArtMethod *) env->FromReflectedMethod(
            rightMethod);
    // 自定义的头文件只是声明,使如下代码通过编译,代码真正执行仍是依靠手机系统中的art_method.h
    artReplaceMethod->access_flags_ = artMethod->access_flags_;
    artReplaceMethod->declaring_class_ = artMethod->declaring_class_;
    artReplaceMethod->dex_code_item_offset_ = artMethod->dex_code_item_offset_;
    artReplaceMethod->dex_method_index_ = artMethod->dex_method_index_;
    artReplaceMethod->hotness_count_ = artMethod->hotness_count_;
    artReplaceMethod->method_index_ = artMethod->method_index_;
    artReplaceMethod->ptr_sized_fields_.dex_cache_resolved_methods_ = artMethod->ptr_sized_fields_.dex_cache_resolved_methods_;
    artReplaceMethod->ptr_sized_fields_.dex_cache_resolved_types_ = artMethod->ptr_sized_fields_.dex_cache_resolved_types_;
    artReplaceMethod->ptr_sized_fields_.entry_point_from_jni_ = artMethod->ptr_sized_fields_.entry_point_from_jni_;
    artReplaceMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = artMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_;
    printf("com.yuan.hotfix 555");
}

核心原理的示意图

三、apk打包流程:

java -> class -> dex -> apk

1. java -> class
Android Studio生成的class文件
\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes\com\yuan\hotfix\andfix\ok\Calculator.class
或者
\build\intermediates\classes\debug\com\yuan\testandfix\ok\Calculator.class

2. class -> dex
借助工具 Sdk\build-tools\28.0.3\dx.bat

  1. 比如在桌面建一个文件夹aa,拷贝\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes\下的com文件夹到aa下,删除不需要打包的class文件,比如只保留需要打包的com\yuan\hotfix\andfix\ok\Calculator.class文件,
    因为Calculator.class里有com.yuan.hotfix.andfix.ok,所以需要com\yuan\hotfix\andfix\ok\一系列的文件夹
  2. cd到如下目录
    C:\Users\ran\AppData\Local\Android\Sdk\build-tools\28.0.3>
    或者把dx.bat配置到环境变量中
  3. 执行
    dx.bat --dex --output C:\Users\ran\Desktop\aa\fix.dex C:\Users\ran\Desktop\aa
    就会把aa文件夹下的所有class打包到aa/fix.dex中

C++实现java方法替换,热修复原理剖析及其实现
andfix热修复.mp4

Anroid分析Andfix原理手写实现
https://blog.csdn.net/qq_23213991/article/details/83342617


ps:
DexFile的API
.so与.dex的区别

相关文章

  • 即时生效热修复

    一、微信 tinker热修复 使用 framework java核心:在加载bug的dex文件前加载补丁dex...

  • 热修复之AndFix探秘

    热修复之AndFix探秘 近几年热修复技术可谓百花齐放,阿里的底层结构替换即时生效技术AndFix,后来又出来看起...

  • 热修复摘要

    参照《深入探索 Android 热修复技术原理》做的摘要。 热修复按生效类型一共分为两种:实时生效和重启应用生效。...

  • 2018-01-03

    android热修复方案 一、概述 热修复就是可以即时修复已经上线的应用程序的bug,省去重新...

  • 【热修复】实时生效&重启生效

    前言 热修复按生效类型一共分为两种:实时生效和重启应用生效。 每种类型按模块分为:Dex 文件修复、res 资源文...

  • 热修复框架

    1.及时生效不可以,就是说需要重启App 才可以加载出新的类,才可以生成新的类。2.热修复指的是bug 修复,这里...

  • [老实李] Android 中的热修复方案总结

    热修复的三个部分 热修复分为三个部分,分别是Java代码部分热修复,Native代码部分热修复,还有资源热修复。 ...

  • JSPath热更新和热修复 个人小结

    热更新和热修复 个人小结 热修复和热更新 1 热更新和热修复:在线修复程序的 BUG 2 JSPach 的使用原理...

  • iptables nat即时生效问题

    iptables nat即时生效问题 background A:kube-apiserver --secure-p...

  • 面试准备——Android热修复

    热修复 什么是热修复 如何进行热修复 热修复解决方案比较 AndFix 基于NDK开发,在native动态替换Ja...

网友评论

      本文标题:即时生效热修复

      本文链接:https://www.haomeiwen.com/subject/htwgtctx.html