Tencent / tinker

Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstall apk.
Other
17.1k stars 3.33k forks source link

针对1.9.14.17的若干修改建议 #1589

Open PhantomQi opened 2 years ago

PhantomQi commented 2 years ago

关于PMDexOpt

triggerPMDexOptOnDemand内部采用了两种突破opt策略:performDexOptSecondary 和 registerDexModule。近期用下面的实验方法做了一次线上灰度实验,得到的结论是绝大部分厂商或机型上registerDexModule能获得更短的补丁加载耗时和更短的opt耗时

  1. 实验组1:完全不做PMDexOpt;
  2. 实验组2:只做registerDexModule;
  3. 实验组3:(除华为荣耀会把registerDexModule作为兜底以外)只做performDexOptSecondary;

这里把结论分享出来,供参考和交流。

onDexModuleRegistered被混淆干掉了

异常类型:app运行时异常

手机型号:已知三星note20出现过

手机系统版本:11

tinker版本:1.9.14.17

gradle版本:无关

是否使用热更新SDK: 无关

系统:无关

堆栈/日志:
AbstractMethodError: abstract method "void android.content.pm.PackageManager$DexModuleRegisterCallback.onDexModuleRegistered"

经过分析,相关代码位置:

private static void registerDexModule(Context context, String dexPath, String oatPath) throws IllegalStateException {
    try {
        ...

        for(int i = 0; i < 2; ++i) {
            ...
            try {
                registerDexModuleMethod.invoke(syncPM, dexPath, new DexModuleRegisterCallback() {
                    public void onDexModuleRegistered(String dexModulePath, boolean success, String message) {
                        ShareTinkerLog.i("Tinker.ParallelDex", "[+] onDexModuleRegistered, path: %s, is_success: %s, msg: %s", new Object[]{dexModulePath, success, message});
                    }
                });

onDexModuleRegistered方法被proguard干掉了。一些机型虽然不会crash,但“onDexModuleRegistered”日志不会打印,也可以证明该方法被干掉了。

“被proguard干掉”问题在tinker的demo上验证可以重现,问题原因是混淆例外规则配置有误,经实验,以下配置方法可解决问题,供参考和交流:

# 有效
-keepclasseswithmembers class * {
    ... onDexModuleRegistered(...);
}

# 有效
-keepclasseswithmembers class com.tencent.tinker.loader.** {
    ... onDexModuleRegistered(...);
}

# 有效
-keepclassmembers class com.tencent.tinker.loader.** {
    ... onDexModuleRegistered(...);
}