快速应用「幽灵调用」的正式修复

今天傍晚,Google将幽灵调用的修复正式合入到R8的诸多版本中,App终于可以用起来了。下面我简单介绍下,再讲下如何在App中快速应用。

整体情况

Google已将修复合入到以下几个R8版本中,注意,是R8版本,而非AGP(Android Gradle Plugin)版本:

  • 8.10.36
  • 8.11.28
  • 8.12.24
  • 8.13.10
  • 9.0.11-dev

对于R8 8.x系列,它们通常会随着 AGP的迭代进入正式版本。举个例子:AGP 目前最新版本是 8.13,未来如果继续发 8.13.1、8.13.2 等小版本,就有可能包含这次 R8 的修复。但也不排除某个大版本只发一次,如果没有新迭代,那这个 AGP 分支就不会带上修复。

而对于即将在下半年发布的 AGP 9.0,Google明确提到会包含此次修复。

当下的解决方案

未来版本什么时候发布我们无法完全确定,那现在该怎么办?

答案是:通过替换 R8 的方式来立即应用修复 。Google 官方提供了操作方法:r8.googlesource.com/r8/#replaci...

To override the embedded version with a prebuilt R8 with version , merge the following into the top level settings.gradle or settings.gradle.kts:

scss 复制代码
pluginManagement {
    buildscript {
        repositories {
            mavenCentral()
            maven {
                url = uri("https://storage.googleapis.com/r8-releases/raw")
            }
        }
        dependencies {
            classpath("com.android.tools:r8:<version>")
        }
    }
}

核心思路很简单:

  • Google 已经把这些修复过的 R8 版本存档在仓库:storage.googleapis.com/r8-releases...
  • 我们只需要在构建脚本里指定这个仓库,并在 classpath 中写入需要的 R8 版本号,就能让 AGP 使用我们指定的 R8,自然也就包含了修复。

实测验证

我在本地项目里亲测了一遍,配置如下:

arduino 复制代码
classpath "com.android.tools:r8:8.10.36"

然后打开 minifyEnabled,编译生成 release APK,并对其中的 classes.dex 执行:

复制代码
dexdump -d classes.dex

结果显示:

sql 复制代码
09a198:                    |[09a198] com.xxx.testdedupe.MyViewA.onDetachedFromWindow:()V
09a1a8: 6f10 540b 0100     |0000: invoke-super {v1}, Landroid/view/View;.onDetachedFromWindow:()V // method@0b54
09a1ae: 6300 0000          |0003: sget-boolean v0, LA/c;.a:Z // field@0000
09a1b2: 3800 0900          |0005: if-eqz v0, 000e // +0009
09a1b6: 6e10 c80a 0100     |0007: invoke-virtual {v1}, Landroid/view/View;.getAlpha:()F // method@0ac8
09a1bc: 0a00               |000a: move-result v0
09a1be: 6e20 900b 0100     |000b: invoke-virtual {v1, v0}, Landroid/view/View;.setAlpha:(F)V // method@0b90
09a1c4: 0e00               |000e: return-void
sql 复制代码
09a1fc:                    |[09a1fc] com.xxx.testdedupe.MyViewB.onDetachedFromWindow:()V
09a20c: 6f10 540b 0100     |0000: invoke-super {v1}, Landroid/view/View;.onDetachedFromWindow:()V // method@0b54
09a212: 6300 0000          |0003: sget-boolean v0, LA/c;.a:Z // field@0000
09a216: 3800 0900          |0005: if-eqz v0, 000e // +0009
09a21a: 6e10 c80a 0100     |0007: invoke-virtual {v1}, Landroid/view/View;.getAlpha:()F // method@0ac8
09a220: 0a00               |000a: move-result v0
09a222: 6e20 900b 0100     |000b: invoke-virtual {v1, v0}, Landroid/view/View;.setAlpha:(F)V // method@0b90
09a228: 0e00               |000e: return-void

虽然字节码内容完全一样,但因为有invoke-super指令,所以无法复用,字节码地址不同表明了这一点。

这就说明修复生效,幽灵调用的问题彻底解决。

相关推荐
xiangpanf3 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx6 小时前
安卓线程相关
android
消失的旧时光-19437 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon8 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon8 小时前
VSYNC 信号完整流程2
android
dalancon8 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013849 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android9 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才10 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶11 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle