遵循最佳实践

使用保留规则时,请务必达到适当的精细度,以确保您在保持应用行为的同时获得益处。如需了解良好的保留规则模式以及应避免的事项,请参阅以下部分。

保留规则中的良好模式

明确定义的保留规则应尽可能具体:

  • 对于类规范,请尽可能指定特定类、基类或带注释的类,如以下示例所示:

    -keepclassmembers class com.example.MyClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers ** extends com.example.MyBaseClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers @com.example.MyAnnotation class ** {
      void someSpecificMethod();
    }
    
  • 应尽可能声明成员规范,并且仅引用必须保留才能使应用正常运行的类部分。建议不要通过将可选成员范围定义为 { *; } 来将规则应用于整个类,除非有严格的需要。

    -keepclassmembers com.example.MyClass {
      void someSpecificMethod();
      void @com.example.MyAnnotation *;
    }
    

如果您无法遵守这些准则,可以暂时将需要保留的代码隔离到专用软件包中,然后将 keep 规则应用于该软件包。不过,这并非长久之计。如需了解详情,请参阅逐步采用优化。如需为软件包使用保留规则,请定义保留规则,如以下示例所示:

-keepclassmembers class com.example.pkg.** { *; }

需要避免的事项

保留规则语法有很多选项,但为了获得可衡量的可持续性能优势,我们建议不要使用以下选项:

  • 避免在保留规则中使用反转运算符 !,因为您可能会无意中将规则应用于应用中的几乎每个类。
  • 请勿使用软件包范围的保留规则,例如 -keep class com.example.pkg.** { *; }(长期)。在配置 R8 时,可以暂时使用它们来解决问题。如需了解详情,请参阅限制优化范围。 一般来说,请谨慎使用通配符,确保仅保留所需的代码。

如果您无法遵守这些规则,则可能使用了大量开放式反射,应避免使用反射或避免使用使用反射的库(请参阅 Gson 案例研究)。