前语

代码稠浊关于每个入门的 Android 工程师来说都不会太生疏,因为在编译正式版别时,这是一个必不可少的进程。而且运用代码稠浊也恰当简略,简略到只需求装备一句minifgradle是什么yEnabljvm内存结构ed true。可是你是否了解稠浊的原理,假定问你代码稠浊究竟做了什么,你会怎么说?


目录

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文


1. 稠浊编译器

假定以稠浊编译器来区其他话,Android 代码稠浊能够分为以下两个时期:

  • ProGuard:一个通用的 Java 字节码优化东西,由比利时团队 GuardSquare 开发
  • R8:ProGuard 的继承者,专jvm调优参数为 Android 规划,编译功用和编译产品更优异

下图梳理了它们跟着 Android Gradle Plugin 版别迭代相应做出的改动:

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

其间,稠浊编译器的改动:

  • 远古: ProGuard
  • 3.2.0:ProGuardgradle版别(默许),R8(引进)
  • 3.4.0:R8(approve默许)

其间:DE架构图怎么做X编译器的改动:

  • 远古: DX
  • 3.0.0:DX(默许),D8(引进)
  • 3.1.0:D8(默许)

假定需求批改 Androidgradle翻译 Gradle Plugin 的默许行为,能够在gradle.properties中增加装备:

  • 启用与禁用 R8
    # 显式启用 R8
    android.enableR8 = true
    
    #架构师薪酬一月多少 1. 只对 Android Library module 停用 R8 编译器
    android.enableR8.libraries = false
    # 2. 对全部 module 停用 R8 编译器
    android.enableR8 = false
    
  • 启用与产品禁用 D8
    #产品营销策划 显式启用 D8
    android.enableD8 = true
    
    # 显式禁用 D8
    android.enableDapprove8 = false
    

其他,假定在运用模块的 buigradle下载慢解决方法ld.gradlappeare 文件中设置useProguard = false,也会运用 R8 编译器代替 Pro架构中考Guard。


2. 四大功用

ProGgradle打包uard 与 R8 都提供了紧缩(shrinker)、优化(optimizer)、稠浊(架构图怎么做obfuscator)、预校gradle打包验(preverifier)四大功用:

  • 紧缩(也称为摇树优化,tree shaking):从 运用及架构规划依托项 中移除 未运用 的类、方法和字段,有gradle教程助于逃避 64 方法数的瓶颈

  • 优化:通过代码 分析 移除更多未运用的代码,甚架构是什么意思至重写代码

  • 稠浊:运用无意义的简略称号 重命名 类/方法/字段,增加逆向难度

  • 预校验:关于面向 Java 6 或许 Java 7 JVM 的 class 文件,编译时能够把 预校验信息 增加到类文件中(StackMap 和 StackMapTable特征),然后加速类加载功率。预校验关于 Java 7 JVM 来说是有必要的,可是关于 Android 平台 无效

运用 ProGuard 时,部分编译流程如下图所示:

  • ProGuard 对 .c产品经理lass 文件实施代码紧缩、优化与稠浊
  • D8jvm内存结构 编译器实施脱糖,并将 .class 文件转换为 .dex文件

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

运用 R8 时,部分编译流程如下图所示:

  • R8 将脱糖(Desugar)、紧缩、优化、稠浊和 dex(D8 编译器)整合到一个进程
  • R8 对 .class 文件实施代码紧缩appearance、优化与稠浊
  • D8 编译器架构是什么意思实施脱糖,并将 .class 文件转换为 .applicationdex文件

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

对比JVM以下 ProGuard 与 R8 :

  • 共同点:

1、开源

2、R8 支撑全部现有 ProGgradle教程uard 规产品运营则文件

3、都提供了四大appleid功用:紧缩优化稠浊预校验

  • 不同点:

1、ProGuard 可用于 Java 项目,而 R8 专为 Android 项目规划

2、R8 将脱糖(D产品质量法esugar)、紧缩、优化、稠浊和 dex(D8 编译器)产品营销策划整合到一个进程中,显jvm是什么意思着提高了编译功用

关于 D8 编译器

将 .class 字节码转化为 .dex 字节码的进jvm调优面试题程被架构师薪酬一月多少称为 DEX 编译,初步是由DX 编译器完毕。与 DX 编译器比较,新的 D8 编译器的编译速度 更快,输出的 .dex 文件 更小 ,却能坚持相同甚至 更超卓 的运用作业时功用


3. 运用示例

不管运用 R8 仍是 ProGuard,架构是什么意思默许不会启用紧缩、优化和稠浊功用。 这个规划首要是出于两方面考虑:一方面是因为这些编译jvm调优面试题时使命会增加编译产品规划时刻,另一方面是因为假定没有充分定义稠浊gradle版别保存规矩,还可能会引进作业时过失。因此,最好 只在运用的查验版别和发布版别中启用这些编译时使命架构,参看运用示例:

// build.gradle
...
android架构图模板 {
buildTypes {
// 查验版别
preview {
// 启用代码紧缩、优化和稠浊(由R8或许ProGuard实施)
minifyEnabled true
// 启用资源紧缩(由Android Gradle plugin实施gradle)
shrinkResources true
// 指定稠浊保存规矩文件
proguardFiles getDefaultProgujvm内存结构ardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
// 发布版别
release {
minifyEnabledapprove true
shrinkResources true
pgradle翻译roguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
// 开发版别
debgradle翻译ug{
minifyEnable产品生命周期d false
}
}
...
}
  • minifyEnabled:(默许状况下)appearance启用代码紧缩、优化、稠浊与预校验
  • shringradle教程kResources:启用资源紧缩
  • proguardFilappstoreesprjvm类加载机制oguardFile:指定 ProGuard 规矩文件,前者能够指定多个参数。下面两段装备的作用是相同的。

    // 方法一:
    proguardFiles getDefaultProgjvm调优面试题uardFile('proguard-andrappreciateoid-gradle教程optimize.txt'), 'progua架构是什么意思rd-rules.pro'
    // 方法二:
    proguardFile getDefaultProguardFile('proguard-android架构-opt架构师和程序员的差异imize.txt')
    proguardFile 'proguard-rulesappearance.pro'
    

前面说到了:不管运用R8仍是ProGuard,紧缩、优化和稠浊功用都是 默许封闭的。通过以下装备能够灵活操控:

  • 全体封闭
minifyEnabled false
// 这行就没有作用了
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.proapple'
  • jvm类加载机制闭紧缩
-dapplicationontshrink
  • 封闭优化(R8 无效)
-dontoptimize

留神:R8gradle装备 不能封闭优化,也不允许批改优化的行为,事实上,R8 会疏忽批改默许优化行为的规矩。例如设置 -ogradle装备ptimizations-optimizationpasses后会得到编译时正告:

AGPBI: {"kind":"warning","text":"Ignoring产品 option: -optimizations","source产品运营首要做什么s":[{"file":"省掉..."}],"tool":"D8"}
AGPBI: {"kind":"w产品运营首要做什么arning","text":"Ig产品规划专业noring option: -optimizationpasses","sources"jvm内存模型:"省掉..."}],"tool":"D8"}
  • 封闭稠浊(主张在开发版别封闭稠浊)
-dontobfuscate
  • 封闭预校验(对 Android 平台无效,主张封闭)
-dontpreverify

4. ProGuard 规矩文件

R8 连续了 ProGuard 运用规矩文件批改默架构图模板许行为的做法。在许多时候,规矩文件也被称为架构是什么意思浊保存规矩文件,这是因为该文件内定义的绝大多数规矩都是和代码稠浊相关的。事实上,文件内还能够定义代码紧缩、优化和预校验规矩,因此称为 ProGuard 规矩文件比较慎重。

在上一节里,咱们说到了运用proguardFilesproguardFile指定 ProGuard 规矩文件。关于任何一个项目,它的 ProGu产品ard 规矩文件有以下三种来历:

  • 1、Android Gradle 插件

在编译时,Android Gradle 插件会生成proguard-android-optimize.txtproguard-android.txt,方位在<module-dir>/build/intermediatjvm调优参数egradle homes/proguard-files/。这两个文件中除了注释之外,仅有的差异是前者apple启用了如下代码紧缩,而后者封闭了代码紧缩,如下所示:

# proguard-android-optimize.txt
-optimizations !code/simplificatijvm调优参数on/arithmetic,!code/sjvm是什么意思implification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
相同部分省掉...
# proguard-android.txAPPt
-dontoptimize
相同部分省掉...

其间相同的架构规划那部分稠浊规矩中,下面这一部分是比较特其他:

-keep产品生命周期 class androidjvm内存结构.supporgradle打包t.annotation.Keep
-keep class androidx.annotation.Keep
// 保产品存@gradle打包Keep注解的类,保存...TODO
-keep @android.架构support.annotation.Keep class * {*;}
-keep @androidx.annotation.Keep class *jvm调优参数 {*;}
// 保存@Keep修饰的方法
-keepclasseswithmembersgradle class * {
@android.support.annotatapproachion.Keep <methods>;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <methods&jvm内存模型gt;;
}
// 保存@Keep修饰的字段
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <fields>;
}
// 保存@Keep修饰的结构方法
-keejvm是什么意思pclasseswit架构师薪酬一月多少hmembers class * {
@android.support.annotation.Keep <init>(.gradle教程..);
}
-keepcla产品sseswithmembers class * {
@androidx.annotation.Keep <init>(...);
}

它指定了与@Keep注解相关的全部保存规矩,这儿就解释了为什么运用@Keep修饰的成员不会被稠浊了吧?

  • 2、Android AsAPPset Package Tool 2 (AAPT2)

在编译时,AAPT2 会依据对 Manifest 中的类、布局及其他运用资源的引证来生成aapt_rules.txt,方位在&approvelt;module-dijvm参数r>/build/intermediates/proguard-rules/debug/架构师aapt_rules.txt
例如,AAPT2 会为 Manifest 中注册的每个组件增加保存规矩:

Referenced at [项目途径]/app/build/intermediatesjvm参数/merged_manifests/release/AndroidManifest.xml:19
-jvm废物回收机制keep class com.have.a.good.time.MainActivity { <init>(); }
省掉...

在这儿,AAPT2 生成了Main架构中考Activity的保存规矩,一同它还指出了引证出处:AndroidManifest.xml:19。这是因为 发起 Activity 的进程中,需求运用反射的方法实例化具体的每一个 Activity ,有爱gradle教程jvm是什么意思能够看下 ActivityThread#performLau产品密钥在哪里能找到nchActivity() -> Iappreciatenstrumentation#newActivity(jvm调优参数)

  • 3、Module

创建新 Mjvm是什么意思odule 时,IDE 会在该模块的根目录中创建一个proguard-rules.applicationpro文件。当然,除了这个主动生成的文件,还可APP以按需创建额定的规矩文件。例如,下面的装备对 releappearase 增加了额定的规矩文件:

...
android {
...
buildTypes {
release {
mappleidinifyEnabled true
proguardFile产品生命周期s getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
productFlavors {
dev{
...
}
release{产品营销策划
proguardFile 'gradle装备release-rules.pro'
}
}
}
...

小结一下:

规矩文件来历 描绘
Android Gradle 插件 在编译时,由 Android Gradle 插件生成
AAPT2 在编译时,AAPTapprove2 依据对运用清单中的类、布局及其他运用资源的引证来生成保存规矩
Module 创建新 Mod架构师薪酬一月多少ule 时,由 IDE 创建,或许其他按需创建

假定将minigradle下载慢解决方法fyEnabled特征设为tgradle翻译rueProGuard 或 R8 会将来自上面列出的全部可用来历的规矩组合在一同。为了看到无缺的规矩文件,能够在proguard-rules.pro中增加以下装备,输出编译项目时运用的全部规矩的无缺陈述:

-prin架构师tconfiguration产品 build/intermediates/proguard-files/full-config.gradle是什么txt

5. 组件化稠浊

在组件化的项目中,需求留神运用 Module 和 Library Module 的行为差异和组件化的资源调集规矩,总结为以下几个要害:

  • 编译时会依次对各层 Library Module进行编译,最底层的 Base Module 会最先被编译为 aar 文件,然后上一层编译时会将依托 Module 输出的 aar 文件/ jar 文件解压到模块的 build 中相应的文件夹中
  • App Module 这一层汇总了全部的 aar 文件后,才真正初步编译操作
  • jvm调优编译的 MoAPPdule 会掩盖之前编译的 Module 中的同名资源

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

运用产品运营首要做什么较高版其他 Android Gradle Plugin,jvm调优面试题不会将汇总的资源放置在 exploded-aar文件夹。即便如此,Lib Module 的资源汇总到 App Module 的规矩是相同的。

咱们通过一个简略示例查验不同装备下的稠jvm参数浊作用:

装备一 装备二 装备三 装备四
App Module 翻开稠浊 X X
Base Mod架构图怎么做ule 翻开稠浊 X X

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

将构建jvm是什么意思的 apk 包拖到 Android Studio 面板上即可分析 Base 类稠浊作用,例如装备一的作用:

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文

全部查验作用如下:

装备一 装备二 装备三 装备四
Ap架构师p Module 翻开稠浊 X X
Base Module 翻开稠浊gradle发音 X X
(作用)Base 类是否被稠浊 X X appear

能够看到,稠浊翻开由 App Module 抉择, 与Lib Module 无关

现在咱们分别在 Lib Module 和 App Module 的 proguard-rules.pro中增加 Base 类的稠浊保存规矩,并在 build.gradle中增加装备文件,查验 Base 类是否能保存:

-keep class com.rui.base.Base

查验作用如下:

装备方位 Lib Module App Module
(作用)Base 类是否保存 X

能够看到:(默许状况)稠浊规矩以 App Module 中的稠浊规矩文件为准

这儿就引进两种干流的组件化approve稠浊计划:

  • 在 App Module 中设置稠浊产品规划专业规矩

这种计划将稠浊规矩都放置到 App Module 的proguard-ruljvm调优面试题es.progradle下载慢解决方法,最简略也最直观,缺陷是移除 Lib Module 时,需求从 App Module 中移除相应的稠浊jvm内存模型规矩。尽管剩余的稠浊规矩并不会构成编译过失或许作业过失,但仍是会影响编译功率。

许多的第三方 SDK,就是采用了这种组件化稠浊计划。在 App Module 中增加依托的一同,也需求在proguard-rules.pro中增加专属jvm废物回收机制的稠浊规矩,这样才华确保releasegradle打包版别正常作业。

  • 在 App Module 中设置公共稠浊规矩,在 Lib Module 中设置专属稠浊规矩

这种计划将专属的产品生命周期稠浊规矩设置到 Lib Module 的prjvm类加载机制og架构师薪酬一月多少uard-rules.pro,可是依据前面的查验,在 Lib Module 中设置的稠浊规矩是不收效的。为了让规矩收效,还需求在 Lib Module 的build.gradle中增加以下装备:gradle是什么

...
android{
defaultConfig{
consumerProguardFiles 'consumer-rules.pro'
}
}

其间consumer-rules.pro文件:

-keep class com.applicationrui.base.Base

查验作用标明,Base 类现已被保存了。这种运用产品营销策划consumerProguardFiles的办gradle打包法有产品生命周期以下几个特征:

  • consumerProguardFiles只对 Lib Module 收效,对 App Module 无效
  • consumerProguardFiles会将稠浊规矩输出为prappearanceoguard.txt文件,并打包进 a产品密钥在哪里能找到ar 文件
  • App Module 会运用 aar 文件中的proguard.txt产品运营首要做什么汇总为究竟的稠浊规矩,这一点能够通过前面说到的-printconfiguration证明

6. 总结产品运营

  • Pgradle下载roGuard 是 Java 字节码优化东西,而 R8 是专为 Android 规划的,编译功用和编译产产品品更优异;

  • ProGuard 与 R8 都提供了四大功用:紧jvm废物回收机制缩、优化、稠浊和预校验。ProGuardjvm参数 首要是对 .class 文件实施代码紧缩、优化与稠浊,再由 D8 编译器实施脱糖并转换为 .dex 文件。R8 将紧缩、优化、稠浊、脱糖和 dex 整合为一个进程;

  • ProGuard 规矩文件有jvm参数三种来历:gradle是什么Android Gradle 插件、AAPT2、Module;

  • 默许状况下,稠浊规矩以 App Module 中的稠浊规矩gradle发音文件为准,运用 consumer-rules.pro 文件能够设置 Lib Module 专属稠浊规矩。


参看资料

  • 紧缩您的运用
  • ProGuarjvm调优d |产品规划专业 Office website
  • ProGuard | Manual
  • R8 | Google Git
  • Android Gradle plugin release njvm内存模型otes
  • 《深化了解Java虚拟机 — JVM高appearance级特性与最佳实践》 周志明 著
  • 《Android 组件架构中考化架构》 仓王 著
  • jvm内存结构Androidgradle下载开发高手课》 张绍文 著,极客时刻 出品

创造不易,你的「三连」是丑丑最大approach的动力,咱们下次见!

Android | 代码混杂究竟做了什么?| 牛气冲天新年征文