Jacky's blog
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)
  • tutorial
  • jetpack

  • components

  • androidx

  • 动态化
  • apm

    • apm相关概念
    • Android稳定性治理
    • Android低端机性能优化
    • monkey测试
    • bitmap
    • 大对象监控
    • android内存
    • 移动端的网络优化
    • 记一次anr问题查询ThreadedRenderer
    • 记一次shrink代码减包调研方案
    • proguard
    • R8
      • Shrink code / code optimize
        • 两者在 R8 流程中位置
        • 共同点
        • 区别点
      • R8 优化详解
        • Shrink(代码缩减)
        • 配置示例
        • Keep 规则示例
        • Optimize(代码优化)
        • 配置示例
        • 优化示例
        • 性能提升
        • 注意事项
        • 最佳实践
      • link
    • perfetto
    • mat
  • module

  • harmony

  • tool

  • other

  • kotlin

  • 《android》
  • apm
Jacky
2024-09-10
目录

R8

# Shrink code / code optimize

# 两者在 R8 流程中位置

  • input jar
    • shrink -> 压缩后的class
    • optimize -> 优化后的class
    • obfuscate -> 混淆后的class
    • preverify -> 混淆后的 jar
  • 经过上述步骤产出 output jar

# 共同点

两者都是在编译期间的优化动作,即在静态情况下,能够确认的一些场景,R8 就会帮忙直接给优化掉

# 区别点

  • shrink 可以认为是类、方法、变量级别的删除。着重注意关键词"删除"
    • 他是在 minifyEnabled=true 后,就会被默认打开的
    • 在编译阶段 agp 会根据程序入口(MainActivity)或者 keep 的类,会画出一个方法调用栈的图,如果一个类、类成员变量、方法完全不在这个调用图上,那么他们将会被删除掉
  • optimize 主要是指对 code 重写,他是深入方法内部的一种重写。着重注意关键词"重写"
    • 他是必须是单独配置才能打开的
    • 举例某个 else 一定不会进入,就会被删掉;如果一个方法只有在某几个地方调用使用,便会被内联到对方类中
    • 某些方法太简单,比如只是简单做一个 if 判断后,就执行一个赋值、打印等,那这个动作会直接被内联到调用方

# R8 优化详解

# Shrink(代码缩减)

  • shrink 可以认为是类、方法、变量级别的删除。着重注意关键词"删除"
    • 他是在 minifyEnabled=true 后,就会被默认打开的
    • 在编译阶段 agp 会根据程序入口(MainActivity)或者 keep 的类,会画出一个方法调用栈的图,如果一个类、类成员变量、方法完全不在这个调用图上,那么他们将会被删除掉

# 配置示例

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
1
2
3
4
5
6
7
8

# Keep 规则示例

# 保持某个类不被删除
-keep class com.example.MyClass { *; }

# 保持某个包下的所有类
-keep class com.example.mypackage.** { *; }

# 保持某个类的特定方法
-keepclassmembers class com.example.MyClass {
    public void myMethod();
}
1
2
3
4
5
6
7
8
9
10

# Optimize(代码优化)

  • optimize 主要是指对 code 重写,他是深入方法内部的一种重写。着重注意关键词"重写"
    • 他是必须是单独配置才能打开的
    • 举例某个 else 一定不会进入,就会被删掉;如果一个方法只有在某几个地方调用使用,便会被内联到对方类中
    • 某些方法太简单,比如只是简单做一个 if 判断后,就执行一个赋值、打印等,那这个动作会直接被内联到调用方

# 配置示例

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            // 启用优化
            proguardFiles 'proguard-optimize.pro'
        }
    }
}
1
2
3
4
5
6
7
8
9
10

# 优化示例

优化前:

class Example {  // 注意:这里使用默认访问修饰符,而不是 public
    private String name;
    
    void setName(String name) {
        if (name != null) {
            this.name = name;
        }
    }
    
    void printName() {
        System.out.println(name);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

优化后:

class Example {
    private String name;
    
    // setName 方法被内联到调用处
    // printName 方法被内联到调用处
}
1
2
3
4
5
6

注意:类的访问修饰符会影响 R8 的优化行为:

  • 使用 public 修饰的类和方法更可能被保留
  • 使用默认访问修饰符(包级私有)的类和方法更容易被优化
  • 建议在不需要对外暴露的类和方法上使用默认访问修饰符,以获得更好的优化效果

# 性能提升

  • 代码大小:通常可以减少 20-60% 的代码体积
  • 启动时间:优化后的应用启动时间通常可以减少 10-30%
  • 内存占用:可以减少 10-20% 的内存使用

# 注意事项

  1. 调试问题:

    • 优化后的代码可能难以调试
    • 建议在开发阶段关闭优化
  2. 反射调用:

    • 使用反射调用的代码需要特别小心
    • 必须添加适当的 keep 规则
  3. 动态加载:

    • 动态加载的类需要特别注意
    • 可能需要额外的 keep 规则
  4. 性能监控:

    • 建议在优化前后进行性能测试
    • 监控关键指标的变化
  5. 常见问题:

    • 类找不到:检查 keep 规则是否完整
    • 方法调用失败:检查方法是否被优化掉
    • 运行时错误:检查反射调用是否正确处理

# 最佳实践

  1. 渐进式优化:

    • 先启用 shrink
    • 确认无问题后再启用 optimize
  2. 规则管理:

    • 使用单独的 proguard 文件管理规则
    • 定期审查和更新规则
  3. 测试策略:

    • 在 CI/CD 流程中加入优化测试
    • 确保所有功能在优化后正常工作
  4. 监控和反馈:

    • 收集优化后的性能数据
    • 根据反馈调整优化策略

# link

  • Code optimization (opens new window)
  • Jake Wharton 的个人博客 (opens new window) 深入字节码理解每项优化的实际原理
上次更新: 2025/04/29, 11:44:15
proguard
perfetto

← proguard perfetto→

最近更新
01
npx 使用指南
10-12
02
cursor
09-28
03
inspect
07-20
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式