【发布时间】:2011-10-28 13:15:00
【问题描述】:
我有一个包含数十条日志记录语句的 Android 应用程序。我希望它们不会出现在发布版本中,所以我在 proguard.cfg 文件中使用了 Proguard 和类似的东西:
-assumenosideeffects class android.util.Log {
public static *** d(...);
}
但问题是Log.d("something is " + something) 很多,虽然Log.d() 语句正在从字节码中删除,字符串仍然存在。
所以,按照this 的回答,我创建了一个简单的包装类,类似于:
public class MyLogger {
public static void d(Object... msgs) {
StringBuilder log = new StringBuilder();
for(Object msg : msgs) {
log.append(msg.toString());
}
Log.d(TAG, log.toString());
}
}
然后我编辑了我的proguard.cfg:
-assumenosideeffects class my.package.MyLogger {
public static *** d(...);
}
但是在生成的字节码中仍然可以找到字符串!
除此之外,我使用的是 Android SDK 提供的标准proguard.cfg。我做错了吗?
编辑:检查生成的字节码后,我看到字符串在那里,但它们并没有像我想的那样被一个接一个地附加。它们被存储在一个数组中。为什么?将它们作为可变参数传递给我的方法。看起来 ProGuard 不喜欢这样,所以我修改了我的 logger 类:
public static void d(Object a) {
log(a);
}
public static void d(Object a, Object b) {
log(a, b);
}
(... I had to put like seven d() methods ...)
private static void log(Object... msgs) {
(same as before)
}
这很难看,但现在字符串在字节码中无处。
这是 ProGuard 的某种错误/限制吗?还是只是我不明白它是如何工作的?
【问题讨论】:
-
你可能想避免 proguard hack,只使用一个常量:stackoverflow.com/questions/4199563/… 如果你使用常量,proguard 将在它 == false 时删除代码行。
-
这确实是一个 hack,而且是一个丑陋的,但我认为这比把
if(DEBUG)到处都好。生成的代码更清晰,并且在导出的应用程序中结果相同。此外,由于某种原因,如果调试常量为假,Eclipse 会抱怨死代码,我不喜欢这样。不过谢谢你的想法:) -
请注意,如果您传递基本数据类型,可能仍然会有一些死代码。 Proguard 不会删除基本数据类型以进行相应的
Object转换。例如。如果你传递了int,Proguard 将离开Integer.valueOf(someVar);