R8 如何优化我们的代码(3) -- 值假设与常量

assumevalues 用法

assumevalues 告知 r8 指定的字段值或者方法值将始终处于特定范围内或等于某个单一值

先看一段简单的代码

kotlin 复制代码
class Count {
    public static void main(String... args) {
        count = 3;
        sayHi();
    }

    private static int count = 1;

    private static void sayHi() {
        if (count < 0) {
            throw new IllegalStateException();
        }
        for (int i = 0; i < count; i++) {
            System.out.println("Hi!");
        }
    }
}

混淆前

混淆后, 不但做了内联,还帮我们做了一定程度上的剪枝处理

再看下我们常用的 android 版本判断

kotlin 复制代码
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        if (Build.VERSION.SDK_INT >= 32) {
            println("32+++")
        } else if (Build.VERSION.SDK_INT >= 31) {
            println("31")
        } else {
            println("<31")
        }

    }
}

假设我们的 min sdk 是 31,

混淆代码以后,代码没有发生什么变化

但是在 proguard 文件中 加入一段代码,因为我们明确知道 我们最小 min sdk 是 31 的

kotlin 复制代码
-assumevalues class android.os.Build$VERSION {
  int SDK_INT return 31..2147483647;
}

再看 r8 混淆后的效果, 嗯这次就符合预期了

注意我们 androidx 里面有大量的 android 版本判断,最低是到 14,所以如果我们可以根据我们项目实际的效果配置这个对应的assumevalues,可以节约不少代码,提高程序执行效率

agp>7.0的版本中我实测是不需要自己手动写Build$VERSION 的assumevalues了,agp 和 r8 会自动配合处理好,这里只是演示一下这个 proguard 写法的作用。

对于部分经常做sdk 的同学来说,在你的 sdk 接入文档中 ,写好对应的assumevalues 也是有助于你 sdk 的性能的,大部分做 app 的知道有这么个东西即可

字符串常量 与类常量

字符串常量的优化 相对而言就不那么重要了,主要是这部分的优化一般情况下 不会引发什么错误,至少我目前还没碰到过 因为字符串常量优化 而导致的运行时 crash 或者 build 失败,大家知道有这么个东西即可

kotlin 复制代码
static String patternHost(String pattern) {
  return pattern.startsWith(WILDCARD)
      ? pattern.substring(WILDCARD.length())
      : pattern;
}

例如上面这段代码,WILDCARD.length() 在 r8 处理之后 会变成一个常量值,避免 程序运行时再去常量池里去找 这里就不具体演示优化前和优化后的字节码了,大家自行体会即可

不过这里大家可能会疑惑,如果不是 activity,是个普通类,还能这样写吗? 按照jw 的原文

的表述,普通类也可以享受此优化,因为 混淆和优化 都是 r8来控制,r8 完全可以做到 先混淆,再优化 这样就可以保证 getSimpleName 方法拿到的值是混淆后的类名。

我这里实验起来的方案来看,当前 r8 版本应该没有做类似的优化了

这里有知道原因的大佬可以评论区里说下原因。

个人猜测,可能是我用于测试的类写的过于简单 导致r8 优化的时候 把我这个类当做是抽象类处理,对于抽象类来说是无法享受此优化的

相关推荐
执明wa14 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio
404_coder14 小时前
源码视角下的 Android 开机流程:从 Zygote、SystemServer 到 Launcher
android
二流小码农15 小时前
鸿蒙开发:以登录案例了解代码架构MVVM
android·ios·harmonyos
用户693717500138415 小时前
从代码生产者到 AI 协作者:软件工程师的角色重构
android·前端·后端
GitLqr16 小时前
别在 Flutter 的 main() 里乱锁屏幕方向,小心 iPad 分屏功能被你搞没了
android·flutter·ios
sg_knight16 小时前
MySQL 存储过程详解:从入门到实战
android·数据库·mysql·database·dba·关系型数据库·db
爱笑鱼16 小时前
Binder(四):ioctl(BINDER_WRITE_READ) 之后,事务怎样到达目标进程?
android
AFinalStone16 小时前
Android 7系统休眠唤醒(二)开机全链路—BootROM到Launcher
android·电源管理·休眠唤醒
Mr YiRan16 小时前
Android NDK开发之统计到未被回收的图片
android