有没有办法防止 Android app code shrinker R8 更改行号?

Is there a way to prevent Android app code shrinker R8 from changing line numbers?

Android Studio 最近开始默认使用 R8 而不是 ProGuard。

尽管对代码进行了混淆处理,但无需使用任何工具即可轻松理解 ProGuard 的堆栈跟踪。让我们使用以下示例:

 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
    at net.foo.anroid.Foo.wb.d(SourceFile:453)
    at net.foo.anroid.Foo.wb.a(SourceFile:213)
    at net.foo.anroid.Foo.wb.n(SourceFile:103)
    at net.foo.anroid.Foo.qa.run(Unknown Source:2)
    at java.lang.Thread.run(Thread.java:764)

通常我确切地知道 net.foo.anroid.Foo.wb 对应于哪个文件,行号(例如 453、213...)是 ProGuard 源文件中的实际行号。

然而,对于 R8,找出哪一行的唯一方法是在 mapping.txt 中查找它们。

这真是一个大麻烦。如果没有好的方法可以从堆栈跟踪中快速定位源代码,我将仅出于这个原因返回 ProGuard。

有没有办法防止R8改变行号?

在 ProGuard 配置中设置这些:

-keepattributes SourceFile,LineNumberTable

然后使用 ReTrace jar:

ReTrace can read an obfuscated stack trace and restore it to what it would look like without obfuscation. The restoration is based on the mapping file that ProGuard can write out during obfuscation. The mapping file links the original class names and class member names to their obfuscated names.

java -jar retrace.jar [options...] mapping_file [stacktrace_file]

例如:

java -jar retrace.jar mapping.txt stacktrace.log

R8 团队不时对此进行讨论,出于多种原因,我们一直在优化行号:

  • 它在 dex 大小上节省了 5% 的区域
  • 对于启用了内联等优化的发布版本,无论如何都需要回溯来扩展内联框架
  • 测试矩阵中少了一个选项

现在,当在配置中同时设置 -dontoptimize(意味着没有内联)和 -dontobfuscate 时,调试版本和发布版本始终处于关闭状态。

当您使用 retrace(记得使用 Proguard 版本 6 或更高版本中的 retrace)时,您不需要删除堆栈跟踪,因为 retrace 将通过未修改的非堆栈跟踪行。

应用程序中目前没有库可以执行此操作,因为这需要将映射文件包含在应用程序中,这违背了使 apk 变小的目的。