【问题标题】:What does the R8 maximumremovedandroidloglevel option?R8 maximumremovedandroidloglevel 选项是什么?
【发布时间】:2022-10-09 17:06:20
【问题描述】:

我目前正在使用常见的 Proguard/R8 配置删除 Android 日志记录:

-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
}

但是我发现了这个official documentation,它也建议使用相应的日志级别(在示例 4 中)设置以下 R8 选项:

-maximumremovedandroidloglevel 4

我查看了 R8 源代码以了解此附加选项的作用。我只找到this comment

将处于或低于某个日志记录级别的 Android 日志记录语句(如 Log.w(...) 和 Log.IsLoggable(..., WARNING) 替换为 false。

这真的需要吗?与仅使用 assumenosideeffects 规则?

【问题讨论】:

    标签: android android-r8


    【解决方案1】:

    我也对这个规则很好奇,所以我研究了一下。

    这真的需要吗?与仅使用假设副作用规则相比有什么好处?
    -maximumremovedandroidloglevel 规则旨在与-assumenosideeffects 具有相同的效果,因此它可以用作完全替代.
    但是,从最新版本 (3.3.75) 开始,它的性能与 -assumenosideeffects 略有不同。如果您打算删除所有 Log.* 方法调用 - 那么您不应该关心(您可以使用一个或另一个)。但是,如果您只删除这些方法的一部分并且依赖Log#isLoggable,那么我建议您坚持当前的配置,并避免将-maximumremovedandroidloglevel 规则添加到您的proguard 配置文件中。


    更深的挖掘

    假设我们的源代码中有以下几行代码,然后我将展示使用不同配置进行 R8 处理后的样子。

    if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) {
        Log.v("FOO_TAG", "verbose message");
    }
    
    if (Log.isLoggable("FOO_TAG", Log.WARN)) {
        Log.w("FOO_TAG", "warn message");
    }
    

    <1>R8 v3.3.75,具有以下规则(注意我已经注释掉了 we 方法):

    -assumenosideeffects class android.util.Log {
        public static boolean isLoggable(java.lang.String, int);
        public static int v(...);
        public static int i(...);
    #    public static int w(...);
        public static int d(...);
    #    public static int e(...);
    }
    

    产生以下输出:

    if (Log.isLoggable("FOO_TAG", 5)) {
        Log.w("FOO_TAG", "warn message");
    }
    

    R8 按预期删除了 VERBOSE 日志。请注意,它保留Log#isLoggable 方法调用,其中级别(第二个参数)为WARN (5)。


    <2>R8 v3.3.75,具有以下规则(4 表示我们要删除直到INFO 的所有日志方法,包括):

    -maximumremovedandroidloglevel 4
    

    产生以下输出:

    Log.w("FOO_TAG", "warn message");
    

    请注意,此规则保留了 Log#w 方法调用,但删除了 Log#isLoggable 调用(这是行为略有不同的地方)。
    这意味着关于 -maximumremovedandroidloglevel 的最新 R8 版本并不像宣传的那样工作 (here):

    示例:android.util.log.INFO 的值为 4。因此, 指定 -maximumremovedandroidloglevel 4 将删除所有对 Log.v()、Log.d() 和 Log.i(),以及它将替换对 Log.isLoggable(X, {2, 3, 4}) 为假。


    <3>来自main 分支的the tip 的R8,具有以下规则(4 表示我们要删除直到INFO 的所有日志方法,包括):

    -maximumremovedandroidloglevel 4
    

    产生以下输出:

    if (Log.isLoggable("FOO_TAG", 5)) {
        Log.w("FOO_TAG", "warn message");
    }
    

    似乎main 分支包含一个修复程序,可以恢复两种方法的行为奇偶性(Log#isLoggableWARN 作为参数没有被删除)。
    main3.3.75 标签之间的相关差异是这两个提交:12


    为什么official documentation 包括-assumenosideeffects-maximumremovedandroidloglevel
    根据我的测试 - 这似乎具有误导性,因为他们应该建议使用其中一种,绝对不能同时使用。

    【讨论】:

      猜你喜欢
      • 2011-08-03
      • 2019-09-08
      • 2019-04-26
      • 2012-08-20
      • 2013-08-26
      • 2010-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多