有没有办法防止Android应用程序代码缩小器R8更改行号?

10

最近,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至少提供了反向过滤器来实现这一点。 - Zoe stands with Ukraine
@Zoe 谢谢你的澄清。能否把你的评论转为答案,方便我接受?是的,我可以用 mapping.txt 来反混淆它,但这很麻烦。 - Hong
2个回答

9

在R8团队中,这个问题已经被时常讨论了,我们选择了始终针对行号进行优化,原因如下:

  • 它可以节省约5%的dex大小
  • 对于打开了像内联等优化的发布版本,仍需要重新跟踪以扩展内联帧
  • 这是测试矩阵中少了一个选项

现在,对于调试版本,它总是关闭的,对于同时在配置中设置-dontoptimize(意味着不内联)和-dontobfuscate的发布版本也是如此。

当您使用retrace(请记得使用Proguard版本6或更高版本的)时,您不需要剪切堆栈跟踪,因为retrace将不会修改非堆栈跟踪行。

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


非常感谢您的解释。我必须承认,我觉得我理解了您解释的80%。我无法使用Retrace恢复原始行号。我正在使用日期为2019-03-31的"C:\ Users \ myid \ AppData \ Local \ Android \ Sdk \ tools \ proguard \ lib"下的ProGuard。使用ReTrace可以正确还原类名和方法名,但是行号保持不变。 - Hong
4
很遗憾,Android Sdk中的ProGuard版本是旧版4.7,问题在于这会导致retrace无法正确显示行号。您需要前往https://sourceforge.net/projects/proguard/files/proguard/6.0/下载最新版本的ProGuard,这样retrace就能正确工作了。 - sgjesse
谢谢。我已经下载并使用了proguardgui.bat。它非常好用。当我从R8的官方页面跳转时,我没有注意到下载按钮。 - Hong

1
请在 ProGuard 配置中设置以下内容:
-keepattributes SourceFile,LineNumberTable

然后使用ReTrace jar

ReTrace可以读取混淆的堆栈跟踪并将其恢复为没有混淆的样子。恢复是基于ProGuard在混淆期间可以写出的映射文件。映射文件将原始类名和类成员名链接到它们的混淆名称。

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

例如:

举个例子:

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

谢谢你在这里提供帮助。我正在尝试避免使用ReTrace。我正在处理应用程序用户报告的调试日志中的堆栈跟踪。日志包含各种信息。从中提取跟踪并将其放入文件中,然后使用ReTrace会很麻烦。我只想查看跟踪,然后打开源代码文件,并使用行号找到问题点。 - Hong
例如,在使用Crashlytics时,mapping.txt文件会自动上传。 - Martin Zeitler
正如我所解释的,我不是在谈论使用上传的mapping.txt进行崩溃分析的问题。我说的是由应用程序生成的堆栈跟踪,这些跟踪包含在应用程序用户发送的调试日志文件中。我认为应用程序无法对代码中的堆栈跟踪进行反混淆。 - Hong
@Hong,你可以将堆栈跟踪文件作为进一步的参数添加;这样就可以实现自动化。 - Martin Zeitler
让我们在聊天中继续这个讨论 - Hong
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接