技术标签: apply changes 编译 dex android 提高编译速度
作为一名Android开发,我们总会面对下面这个按钮,对于一些大型项目,或者对于在编译期间做了很多task的工程都会花去相当多的时间。就我而言,经常跑一个debug的包需要3分钟左右,当跑release的包需要10分钟左右,如果是一些性能差的电脑,这个时间会消耗的更多。今天文章的主题有两个部分,一个是Android的编译都做了哪些事,还有一个是如何提高我们的编译是速度以及相关原理。
今天的主题将围绕下面这个按钮开始讲述。
大家在刚学计算机基础这门课程的时候就知道,“计算机只认识0和1,我们写的编译程序经编译器翻译成由0和1构成的二进制格式才能由计算机执行”。所以,我们写的java语言或者kotlin语言最终都会转化成0,1的二进制数据。在这里,这些二进制数据有一个名字—字节码(各种不同平台的虚拟机与所有平台都统一使用的程序存储格式)。在java虚拟机中,使用java编译器可以把java代码编译为存储字节码的Class文件。Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在Class文件中。对于具体的词法分析、语法分析以及底层编译原理就不在这里细讲了。
具体看下下面的图。
你可以把编译简单理解为,将高级语言转化为机器或者虚拟机所能识别的低级语言的过程。对于 Android 来说,这个过程就是把 Java 或者 Kotlin 转变为 Android 虚拟机运行的Dalvik 字节码(DEX文件)的过程。
javac Sample.java // 生成Sample.class,也就是Java字节码
// javac -source 1.8 -target 1.8 Sample.java 也可以通过指定版本与dex对应上
javap -v Sample // 查看Sample类的Java字节码
//通过Java字节码,生成Dalvik字节码
dx --dex --output=Sample.dex Sample.class
dexdump -d Sample.dex // 查看Sample.dex的Dalvik的字节码
//javac .class
public void test();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String 哈哈哈哈
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 8: 0
line 9: 8
平台支持区别
Dalvik:Android 4.4及其以下系统使用。
ART:Android 4.4以上系统使用。
工作原理区别
我们经常点击构建按钮,就会看到Android studio下方开始不停的执行task,最终会生成一个APK并打开我们设置的launch Activity
。以官方的话来说,
Android 编译系统会编译应用资源和源代码,然后将它们打包成可供您测试、部署、签署和分发的 APK。我们具体可以看下整个构建流程。
总共可以分为以下4部分
在上文我们了解到我们的java和kotlin代码会被Android虚拟机转化成dex文件,那我们的资源文件以及xml又是如何打包的呢。我们来了解下 AAPT2
AAPT2(Android 资源打包工具)是一种构建工具,Android Studio 和 Android Gradle 插件使用它来编译和打包应用的资源。AAPT2 会解析资源、为资源编制索引,并将资源编译为针对 Android 平台进行过优化的二进制格式。
AAPT2 支持通过启用增量编译实现更快的资源编译。这是通过将资源处理拆分为两个步骤来实现的:
这里我们来讲讲增量编译相关优化方案
增量编译–对用户源程序局部修改后进行的重新编译的工作只限于修改的部分及与之相关部分的内容。相关部分的确定由编译系统确定,对用户是透明的。增量编译对软件开发,尤其是在调试期,可以大大缩短编译时间, 提高编译效率,这也是增量编译的优势所在。
我们在上文了解了整个apk的构建流程,每次正常打apk都需要完整的链路走过一次,假设我们只改动了部分代码,能不能只编译我们改动的部分,其余的部分利用缓存机制,来帮助我们快速构建apk呢。
我们来看下目前市面上已有的编译方案。
Instant Run的作用是使得开发过程中的改动可以不用完整编译并重新安装app就能应用,也就是更快看到改动的实际效果,节省时间。实现的原理是通过修改原先的构建过程在初始编译中实现插桩,在后面的改动中只编译改动的部分,并把产物推送到设备上,并通过植入app中的runtime加载新的变动。
因为 instant-run
存在一些弊端,在 Android Studio 3.5 及更高版本中,Apply Changes
可让您将代码和资源更改推送给正在运行的应用,而无需重启应用(在某些情况下,甚至无需重启当前的 Activity)。但是Apply Changes
使用搭载 Android 8.0(API 级别 26)或更高版本的设备上支持。
在 Android Studio 3.5 及更高版本中,Apply Changes 可让您将代码和资源更改推送给正在运行的应用,而无需重启应用(在某些情况下,甚至无需重启当前的 Activity)。
Apply Changes 使用搭载 Android 8.0(API 级别 26)或更高版本的设备上支持的 Android JVMTI 实现中的功能。对于UI的改动,我们能通过apply changes快速在手机中查看我们修改的地方。
同时,也存在一定限制:
某些代码和资源更改必须在重启应用之后才能应用,其中包括以下更改:
整体设计需要考虑两个点
我们看下Apply Changes
整体框架图
在后台进程中利用D8的DEX文件分析功能来检查Android Studio部署到设备上的每个.dex文件的内容。在.dex文件中的各个类上计算基于校验和的指纹,并将结果临时存储在主机工作站上的缓存数据库中。通过将新编译的指纹与以前的编译的指纹进行比较,“应用更改”能够在短时间内有效地提取更改的类。
“应用更改”需要计算安装的APK与最近构建的APK之间不同的文件,而不必从设备中提取所有内容。这次,它仅获取压缩文件的中央目录,并保守估计相应APK之间的差异。通过仅传输已更改的部分,Android Studio传输的数据比完整的APK上传要少得多。在大多数使用情况下,总有效负载减少到几个KiB,而不是几个MiB。
BUCK建立了一套完善的依赖规则以及细化的缓存系统来缩减编译时间,其增量构建的原理,实际是以工程目录为单位进行增量构建,发生变更时候,变更的工程,以及该工程作为父节点或祖先节点的工程,均需要重新构建。无论是 Buck 的exopackage
,还是代码的增量编译,Buck 都更加高效。Buck还有分包支持,ReDex 支持等功能。
但是BUCK的整体接入成本还是比较高的。要去掉原有的gradle方案
多任务并发,多级缓存,增量范围最小化,懒加载,基于长链接无安装式运行期动态替换,基线对齐触发机制,可调试。详细细节可以参考 Freeline的官方文档。
更换编译机器。装备升级,CPU升级效果杠杠的。
升级 Gradle 和 SDK Build Tools。在新版本中,Android致力于优化Gradle的构建。
采用上述增量编译方案的某一种。
对于debug测试包,我们关心apk构建的速度以便我们能快速开发。而对于需要发布的release包,我们更关心包的大小以及性能的稳定。
接入proGuard后,我们的app构建流程将变化如下。
d8 是一种命令行工具,Android Studio 和 Android Gradle 插件使用该工具来将项目的 Java 字节码编译为在 Android 设备上运行的 DEX 字节码,该工具支持您在应用的代码中使用 Java 8 语言功能。
当您使用 Android Gradle 插件 3.4.0 或更高版本构建项目时,该插件不再使用 ProGuard 执行编译时代码优化,而是与 R8 编译器协同工作。
在编译时做了以下事情
R8 的最终目的 加快编译速度,更强大的代码优化。
ReDex是Facebook开源的Android字节码(dex)优化器,它直接输入的对象是 Dex,而不是“.class”文件。ReDex拥有目前更强大的编译速度以及代码优化。具体配置可以参考 Redex官方。能有效的降低包提及,优化了android原有的打包策略。
对于如何提高编译速度, google在每个版本升级中都进行了优化,同时,行业内也开源了自身的好的编译方案,对于我们日常的业务开发中,可以根据自身的业务需求来选择方案。
对于我们日常的debug开发,为了能快速看到我们相关功能的具体实现。增量编译的速度成为了关键,在编译过程中,我们看到了一些代码插桩的技术。将在之后给各位详细介绍Android中如何进行代码插桩的方案和一些用例。
https://time.geekbang.org/column/article/82468
https://source.android.com/devices/tech/dalvik/dalvik-bytecode
https://developer.android.com/studio/build?hl=zh-cn
https://developer.android.com/studio/command-line/aapt2?hl=zh-cn
文章浏览阅读2.8k次。pip3 install -i https://pypi.douban.com/simple pycryptodomePyCrypto 已死,请替换为 PyCryptodome_crypto库的安装linux
文章浏览阅读3.9w次,点赞18次,收藏110次。使用PLSQL Developer中的ODBC导入器将Excel表导入Oracle数据库_odbc导入器
文章浏览阅读1.9k次。原文链接:http://www.cnblogs.com/bluejoe/p/5115888.html最近对Activiti做了一些深入的研究,对Activiti的流程机制有了些理解,对动态调整流程也有了一些实践方法。现在好好总结一下,一来是对这段时间自己辛苦探索的一个记录,二来也是为后来者指指路~~~如下内容准备采用QA的方式写,很多问题都是当初自己极疑惑的问题,希望能为大家解惑!Q:..._activiti6 动态修改流程
文章浏览阅读2w次,点赞4次,收藏43次。Modbus通讯数据格式:单个写入多个写入读取Modbus功能码:功能码 名称 作用1 读取线圈状态 取得一组逻辑线圈的当前状态(ON/OFF)2 读取输入状态 取得一组开关输入的当前状态(ON/OFF)3 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值4 ..._modelbus协议功能码
文章浏览阅读1.6k次,点赞2次,收藏18次。目录包含希腊字母包含上标和注释TeX 标记选项包含 LaTeX 行间数学公式的文本图文本中的希腊字母和特殊字符是可以使用 TeX 标记向图中添加包含希腊字母和特殊字符的文本。此外,还可以使用 TeX 标记添加上标、下标以及修改文本类型和颜色。默认情况下,MATLAB支持一部分 TeX 标记。要使用其他特殊字符,如积分和求和符号,可以改用 LaTeX 标记。此示例说明如何向图文本中插入希腊字母、上标和注释,并解释其他可用的 TeX 选项。包含希腊字母创建一个简单的线图并添加标题._matlab图文本中的希腊字母
文章浏览阅读3.4k次。arm64以及amd64和龙芯4000下安装pyqt:包下载地址:sip安装包地址:https://riverbankcomputing.com/software/sip/downloadqt源码下载 http://download.qt.io/arhive/qt/2.7下安装pyqt5:https://www.cnblogs.com/deeplearning1314/p/10671347.html参考编译链接:linux下安装qt:https://blog.csdn.net/u01452338_generating the c++ source for the qtcore module...error: unable to create th
文章浏览阅读1.8k次,点赞4次,收藏34次。目录IDEA的快捷键IDEA基本设置★★★jdk设置★★★settings界面介绍一、切换主题二、背景设置三、字体设置四、注释设置五、系统设置六、编码设置七、智能提示忽略大小写八、重复代码横线去除九、设置文件代码模板十、修改servlet模板十一、自定义代码颜色十二、设置鼠标滚轮调节字体大小十三、设置鼠标放在方法上或者变量上会弹出注释说明十四、IDEA给选中内容添加双引号""十五、设置自动导包十六、设置代码显示行号及方法分._j2eecfgfile插件怎么用
文章浏览阅读2.2k次。项目中我们经常用到menu菜单栏,系统给出的默认为黑色的,有时候不符合我们项目中的需要,这就需要我们对状态栏给出一些改变。:解决方案一:在style中配置给出menu的样式,通常情况下,这种方案能决绝大部分需求 <style name="MenuTextStyle"> <item name="android:textColor&_android menuitem文字颜色
文章浏览阅读829次。itedbtitle =Request("title")(1); itedbname =Request("name")(1); itedbsource =Request("source")(1); itedbtype =Request("select")(1); itedbcct =Request("content")(1); var conn =Server.CreateObject("ADO_if函数将表中数据填到另一个表
文章浏览阅读2.3k次。pip install torch===1.7.1+cu110 torchvision===0.8.2+cu110 torchaudio===0.7.2 -f https://download.pytorch.org/whl/torch_stable.html -i https://pypi.douban.com/simple/_cuda11.2安装torch
文章浏览阅读1.3k次。推荐阅读:1.ips细胞再生视网膜研究进展2.iPS细胞重编程实验相关实验材料四因子作用那么,是否可以直接应用相关转录因子对体细胞进行重编程而逆转终未分化细胞的发育潜能, 进而表现出ES细胞那样的多潜能性呢?Takahashi和Yamanaka{4}选择24种在小鼠早期胚胎ES细胞或者肿瘤细胞中丰富表达的转录因子, 通过筛选、组合, 发现用Oct4, Sox2, c-Myc和Klf4 4个因子(这4个因子也被称为Yamanaka因子)可以有效地将胎鼠成纤维细胞(mouse embryonic _成纤维细胞为什么用于ips
文章浏览阅读3.8k次。之前发表过chatterbot 的自定义api本人的流程 但是有粉丝或游客私信我 怎样对接自己个人微信 现在统一回复下 自己的心得流程 实现等在写代码之前我先表述下 之前个人微信接口 使用itchat 等 在使用这类的前提是可以 登录网页版微信 网页版微信登录链接 itchat原理就是一种爬虫 获取绘话信息处理并返回自定义信息(跑远了…) 要想获取个人微信中的对话 必须登录 才能自定义一些逻辑啥的前几天自己写了能实现对接chatterbot的api接口1 首先我们要绕过登录验证 能成功登录