在ProGuard的优化删除未使用的字符串字符串、ProGuard

2023-09-12 01:05:39 作者:江河日暮

我有这ProGuard的配置,以去掉调试日志报表时,我发布一个Android应用程序:

I include this ProGuard configuration to strip out debug log statements when I release an Android application:

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}

这工作正常—我可以调用,如 Log.d(这是一个调试语句)ProGuard的日志和Android日志输出中看到; 被删除

This works as expected — I can see from the ProGuard logs and Android log output that calls such as Log.d("This is a debug statement"); are removed.

不过,如果我反编译现阶段的应用程序,我仍然可以看到所有被用来与mdash的字符串文字;即这是在这个例子调试语句

However, if I decompile the app at this stage, I can still see all the String literals that were used — i.e. This is a debug statement in this example.

有没有办法也删除每个字符串就是不再从字节code需要?

Is there a way to also remove each String that's no longer needed from the bytecode?

推荐答案

ProGuard的可去除简单的常量参数(字符串,整数,等)。因此,在这种情况下,code和字符串常量应该完全消失:

ProGuard can remove simple constant arguments (Strings, integers, etc). So in this case, the code and the string constant should disappear completely:

Log.d("This is a debug statement");

不过,您可能已经有一些code这样的观察到的问题:

However, you may have observed the issue with some code like this:

Log.d("The answer is "+answer);

编译之后,这实际上相当于:

After compilation, this actually corresponds to:

Log.d(new StringBuilder().append("The answer is ").append(answer).toString());

ProGuard的4.6版本可以简化这是这样的:

ProGuard version 4.6 can simplify this to something like:

new StringBuilder().append("The answer is ").append(answer).toString();

所以日志不见了,但优化步骤仍留下一些绒毛。这是令人惊讶的技巧来简化这个没有一些有关StringBuilder类更深入的了解。至于ProGuard的来讲,它可以说:

So the logging is gone, but the optimization step still leaves some fluff behind. It's surprisingly tricky to simplify this without some deeper knowledge about the StringBuilder class. As far as ProGuard is concerned, it could say:

new DatabaseBuilder().setup("MyDatabase").initialize(table).close();

有关人,StringBuilder的code能明显被删除,但DatabaseBuilder code恐怕不能。 ProGuard的需要逃逸分析和其他一些技术,这是不是在这个版本呢。

For a human, the StringBuilder code can obviously be removed, but the DatabaseBuilder code probably can't. ProGuard requires escape analysis and a few other techniques, which aren't in this version yet.

至于解决办法:你可以创建采取简单的参数额外的调试方法,并让ProGuard的删除这些:

As for a solution: you can create additional debug methods that take simple arguments, and let ProGuard remove those:

MyLog.d("The answer is ", answer);

另外,您也可以尝试prefixing每一个调试语句和条件的ProGuard以后可以评估为假。此选项可能有点比较绕口,需要在一个初始化方法对于调试标志一些额外的-assumenosideeffects选项。

Alternatively, you can try prefixing every debug statement with a condition that ProGuard can later evaluate as false. This option may be a bit more convoluted, requiring some additional -assumenosideeffects option on an initialization method for the debug flag.