在 ProGuard 优化期间删除未使用的字符串 [英] Removing unused strings during ProGuard optimisation

查看:28
本文介绍了在 ProGuard 优化期间删除未使用的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我包含这个 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(...);
}

这按预期工作—我可以从 ProGuard 日志和 Android 日志输出中看到,删除了诸如 Log.d("This is a debug statement"); 之类的调用.

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.

然而,如果我在这个阶段反编译应用程序,我仍然可以看到所有使用过的 String 字面量 —即 这是本例中的调试语句.

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.

有没有办法同时从字节码中删除每个不再需要的String?

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

推荐答案

ProGuard 可以删除简单的常量参数(字符串、整数等).所以在这种情况下,代码和字符串常量应该完全消失:

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");

但是,您可能已经观察到了这样一些代码的问题:

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 代码显然可以删除,但 DatabaseBuilder 代码可能不能.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);

或者,您可以尝试为每个调试语句添加一个条件前缀,ProGuard 稍后可以将其评估为 false.这个选项可能有点复杂,需要在调试标志的初始化方法上使用一些额外的 -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.

这篇关于在 ProGuard 优化期间删除未使用的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆