原文链接

https://blog.csdn.net/jamin0107/article/details/81123154

〇.序
将.class自己码转化为.dex字节码作为Apk打包的关键步骤,Google打算在Android 3.0中引入D8作为原先Dex的升级版,以及R8作为原本Proguard 压缩与优化(minification、shrinking、optimization)部分的替代品。升级Dex编译器将直接影响构建时间,.dex文件大小,运行时性能。

一.D8
1.1 D8 的功能是把java字节码转化成dex代码,D8作为DX的一个替换方案。
谷歌通过自己的 基准测试项目测出,编译时间缩短了20%,而且.dex文件更小,虽然只有几个百分比。D8编译的.dex文件将拥有相同或者是更好的运行时性能。

Java 8支持相关
Android Studio 3.0 及以上版本支持所有 Java 7 语言功能,以及部分 Java 8 语言功能(具体因平台版本而异)。 
注:在开发 Android 应用时,可以选择使用 Java 8 语言功能。 您可以将项目的源代码和目标代码兼容性值保留为 Java 7,但仍须使用 JDK 8 进行编译。 
Android Studio 为使用部分 Java 8 语言功能及利用这些功能的第三方库提供内置支持。 如图 1 所示,默认工具链对 javac 编译器的输出执行字节码转换(称为 desugar),从而实现新语言功能。 Jack 不再受支持,您需要首先停用 Jack 才能使用默认工具链内置的 Java 8 支持。

目前Java 8语言支持的处理是在javac之后,与字节码处理工具处理之前。在接下来的几个月,这个步骤将会被移动到pipeline的后一个阶段,作为D8的一部分。

其带来的影响:
减少这块的编译时间
可以优化更多代码
这么一来,所有字节码处理工具就必须要支持Java8的字节码格式了。
1.2 D8的使用
已经在Android Studio 3.0 Beta release中引入

Android Studio 3.0 
需要主动在gradle.properties文件中新增:android.enableD8=true
Android Studio 3.1或之后的版本 
在3.1或之后的版本D8将会被作为默认的Dex编译器。如果遇到问题,你可以通过修改gradle.properties文件里的一个属性恢复到DX android.enableD8=false
除了其他好处外,使用D8还有一个好处,就是支持 脱糖,让Java 8才提供的特性(如lambdas)可以转换成Java 7特性。把脱糖步骤集成进D8影响了所有读或写.class字节码的开发工具,因为它会使用Java 8格式。你可以在gradle文件中设置一个属性,恢复到以前的行为,让脱糖发生在Java编译之后,.class字节码仍遵循Java 7格式:android.enableD8.desugaring = false

1.3脱糖(Desugar)
当我们选择JDK8以上版本时,有时候会使用lambda表达式,在设置android.enableD8.desugaring = false的时候。编译链会对lambda表达式进行一次脱糖处理。请看下面的例子。

1.3.1 纯函数脱糖
源代码很简单:
一个简单的Activity,设置ClickListener一种是Java7以下的传统写法,一种是Java8的Lambda表达式写法

public class MainActivity extends Activity {@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = findViewById(R.id.click);//lambda写法tv.setOnClickListener(view -> {Log.d("MainActivity", "MainActivity");});//普通写法tv.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View view) {Log.d("MainActivity", "MainActivity");}});}
}

编译后的Class文件如下:
路径为 
app/build/intermediates/transforms/desugar/release(buildType)/0/com.jamin.d8desugar(packageName)/

public class MainActivity extends Activity {public MainActivity() {}  protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.setContentView(2130968576);TextView tv = (TextView)this.findViewById(2130903040);//直接使用Lambda表达式脱糖后的静态引用tv.setOnClickListener(MainActivity$$Lambda$0.$instance);tv.setOnClickListener(new OnClickListener() {public void onClick(View view) {Log.d("MainActivity", "MainActivity");}});}
}

//Class文件中生成静态引用

final class MainActivity$$Lambda$0 implements OnClickListener {static final OnClickListener $instance = new MainActivity$$Lambda$0();private MainActivity$$Lambda$0() {}public void onClick(View var1) {MainActivity.lambda$onCreate$0$MainActivity(var1);}
}

实际上非D8脱糖,为了保证JAVA7及以下的兼容性。是将lambda表达式的在javac编译class的时候就已经将lambda表达式转化成更高兼容度的低版本代码。好处是在编译链中,有时候会使用一些java7的工具。他们对于java8的语法糖是无法识别的。

1.3.2 非纯函数脱糖
好,我们简单改写一下源文件

public class MainActivity extends Activity {String abc = "abc";  @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = findViewById(R.id.click);tv.setOnClickListener(view -> {Log.d("MainActivity", "MainActivity" + abc);});tv.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View view) {Log.d("MainActivity", "MainActivity" + abc);}});}
}

生成的class文件如下:

public class MainActivity extends Activity {String abc = "abc";public MainActivity() {}  protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.setContentView(2130968576);TextView tv = (TextView)this.findViewById(2130903040);//注意this传递过去了。类似于内部类的写法tv.setOnClickListener(new MainActivity$$Lambda$0(this));tv.setOnClickListener(new OnClickListener() {public void onClick(View view) {Log.d("MainActivity", "MainActivity" + MainActivity.this.abc);}});}
}
// $FF: synthetic class
final class MainActivity$$Lambda$0 implements OnClickListener {private final MainActivity arg$1;MainActivity$$Lambda$0(MainActivity var1) {this.arg$1 = var1;}public void onClick(View var1) {this.arg$1.lambda$onCreate$0$MainActivity(var1);}
}

此时生成的class文件就不是纯函数了。所以会不会内存泄漏?

1.3.3 D8脱糖
在设置android.enableD8.desugaring = true的时候(高版本,比如AGP的版本是com.android.tools.build:gradle:3.3.0-alpha03时,默认是D8脱糖),D8脱糖就不会在transforms目录下生成desugar目录。反编译transforms/dexBuilder/中的jar包。可以看到在jar包中,已经是脱糖后的结果了。大家可以看下图。也是把lambda表达式生成一个静态对象。

当然D8脱糖,要求编译链中所有工具都支持java8,不然不认识class文件中的部分语法糖。D8脱糖的好处是什么呢。官方的话说就是可以提高编译速度。

二.R8
R8作为原本Proguard 压缩与优化(minification、shrinking、optimization)部分的替代品,依然使用与Proguard一样的keep规则。 
目前R8已经开源: r8/r8,其包含了D8与R8。

目前R8还没有整合进Android Gradle plugin,不过由于其已经开源,根据文档可以很快的在python环境下运行起来:

确保本地已经安装了python 2.7或更高版本(macOS Sierra自带python 2.7)。
由于R8项目使用chromium项目提供的depot_tools管理依赖,因此先安装depot_tools
Clone R8项目:git clone https://r8.googlesource.com/r8 && cd r8
下载一个Gradle版去编译,并且声称两个jar文件: build/libs/d8.jar与build/libs/r8.jar: python tools/gradle.py d8 r8 
根据r8文档进行使用即可
BREAKING NEWS:新版AndroidStudio可以体验一下。
New code shrinker 
R8 is a new tool for code shrinking and obfuscation that replaces ProGuard. You can start using the preview version of R8 by including the following in your project’s gradle.properties file: 
android.enableR8 = true

官方文档: New code shrinker

参考资料

  • Android Studio switching to D8 dexer
  • Next-generation Dex Compiler Now in Preview
  • 官方文档 : 使用 Java 8 语言功能

Android Studio 3.0+ 新Dex编译器D8 Desugar R8相关推荐

  1. Android Studio 4.0 新功能与优化

    1.前言 Android Studio又更新了,每次重大更新都给我们的生产力提升了一个台阶,当然也会带来神奇的bug,墙裂提醒各位小伙伴升级请慎重!!! [真香警告]Android Studio下载链 ...

  2. android studio 3.0新功能介绍

    谷歌2017发布会更新了挺多内容的,而且也发布了AndroidStudio3.0预览版,一些功能先睹为快.(英语一般,有些翻译不太好) 下载地址 https://developer.android.g ...

  3. 神经网络API、Kotlin支持,那些你必须了解的Android 8.1预览版和Android Studio 3.0新特性

    曾仅用 55 秒发布会的 Android 8.0 Oreo 在时隔两个月后,Google 于今天在其官方网站上正式发布了 Android 8.1 首个开发者预览版,此次升级涵盖了针对多个功能的提升优化 ...

  4. Android studio 4.2新特性及升级异常

    Android studio 版本及特性系列目录 Android 12 终于来了,你准备好了吗? Android studio 4.2新特性 Android studio 4.1新特性 Android ...

  5. android 编译器有问题,Android Studio 3.0 Beta 2发布:解决编译器bug

    5月18日,IT之家曾经报道,谷歌发布了Android Studio 3.0的测试版,新增了对Kotlin语言的支持,而日前,谷歌发布了Android Studio 3.0的Beta 2版本. 此版本 ...

  6. android 模拟器 2.0,Android Studio 2.0 之 新的模拟器

    上个星期,Android Studio 2.0 的稳定版终于发布了,于是我马上兴冲冲的升级了. Android Studio 2.0 最突出的主新特性有两个: Instant Run -- 即时运行, ...

  7. visual studio 最新稳定版本_速来围观!Android Studio 4.0 稳定版发布了

    作者:恋猫de小郭 Android Studio 4.0(2020年5月) 更新啦!此版本包含了各种新功能和改进,还有一些废弃配置. 重要提示:更新后,需要重新启动 Android Studio 才能 ...

  8. Android Studio 3.0 正式版本 发行说明 (翻译)

    前言 as终于发正式版了.赶快来看看有什么新的功能.本文采用翻译器翻译. Android Studio是为Android开发的官方IDE,包含构建Android应用程序所需的一切. 1.要获取最新版本 ...

  9. Android Studio 4.0 稳定版发布了

    Android Studio 4.0(2020年5月) 更新啦,此版本包含了各种新功能和改进,还有一些废弃配置. 重要提示:更新后,需要重新启动 Android Studio 才能应用从早期版本的 I ...

最新文章

  1. 梯度算法求步长的公式_LM(Levenberg-Marquarelt)算法
  2. 自动驾驶车辆何时实现?近期不会实现的五大原因
  3. 【POJ1144】Network
  4. VM:Vmware简介、安装、使用方法详细攻略
  5. 云信小课堂|如何实现音视频通话
  6. 解决Eclipse代码分析插件SonarLint在Console输出乱码问题
  7. 机器学习基础-神经网络-10
  8. Android 中的 Context
  9. 女朋友心血来潮帮我清洗电脑
  10. 斜杠青年Ruff:区块链只是分内事
  11. es为mysql创建索引_ES(ElasticSearch) 索引创建
  12. cat >> ipconf << EOF > EOF是什么意思
  13. Java课程报告实验总结,java实验报告总结 [Java课程设计实验报告]
  14. 网络安全:漏洞测试主要平台 BackTrack4+Metasploit+ruby
  15. cad2019菜单栏怎么调出来_AutoCAD2019工具栏怎么调出来 工具栏没了找不到解决方法...
  16. python实现屏幕截图_Python实现计算机屏幕任意区域截图
  17. linux 切换 amd 显卡,ubuntu 14.10 (64位)下载amd显卡,实现双显卡切换
  18. VS之Excel文件操作
  19. STM32F407 STM32F407 LWIP速度优化测试速度可以达到1万kb每秒 相当于80兆的网络速度
  20. parameterType和@Param注解用法

热门文章

  1. 武汉大学计算机音乐,名家论坛丨预告:聆听音乐
  2. 记录h5文件数据转为npy和csv格式类型的方法
  3. 高含金量国际计算机编程竞赛
  4. 在安卓项目中使用gifsicle编辑GIF动图-Android NDK 编译 gifsicle 为可执行文件记录
  5. 【iOS开发】—— SDWebImage源码学习(未完)
  6. 微信公众号平台服务器配置请求url超时,绑定微信公众平台提示请求URL超时怎么办...
  7. RAID 独立冗余磁盘阵列详解(RAID 0、RAID 1、RAID 5、RAID 10)
  8. ACRush 楼天城 回忆录
  9. 连连看修改(golang)
  10. 来,我们谈谈怎么选购一台笔记本