android - 使用 ProGuard 删除日志不会删除正在记录的字符串

标签 android proguard

Possible Duplicate:
Removing unused strings during ProGuard optimisation

我有一个包含数十条日志记录语句的 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 不够智能,无法删除所有未使用的代码。

java 编译器将可变数量的参数编译为单个数组参数。在调用方面,这意味着创建一个大小合适的数组,填充元素并将其传递给方法。 ProGuard 看到正在创建数组,然后用于在其中存储元素。它没有意识到(还)它没有用于实际有用的操作,方法调用消失了。结果,数组的创建和初始化被保留了。

如果您期望某些特定的优化,最好检查已处理的代码。

关于android - 使用 ProGuard 删除日志不会删除正在记录的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7086920/

相关文章:

java - 错误:发生了JNI错误。线程 “main” java.lang.VerifyError中的异常。该位置的预期堆栈图框架

android - 添加 jar 库和包含库的 src 之间的安全差异

Android 应用程序在使用 proguard 发布时崩溃

proguard - 从 Proguard 的保留规则中排除某些类

java - 从 FileObserver 启动 IntentService

java - 禁用警告变量可能尚未初始化?

Android-从 Activity 中启动另一个应用程序

Android 全屏警报对话框

Android混淆器: Classes and Resources extractable even after using Proguard

android - 协程中的 Job.Cancel 与 Scope.Cancel 有什么区别?