友情提示,这是一篇硬货,建议静心阅读。

敲黑板,先来讲几个术语:

1. JIT

全称是Just-in-time,即时编译;当Java字节码运行在JVM上的时候,JVM实时得把字节码编译成机器码就叫JIT。

2. AOT

全称是Ahead-of-time,预先编译;与JIT对应,你JIT不是实时的吗?那我先提前编译好,就是AOT。

3. IR

全程是Intermediate representation,即中间表示。中间表示是一个从原始表示到目标表示之间的中间层。

现代编译器分为前端和后端,前后端的分界线就是IR。

现代编译器的大致流程:词法分析->语法分析->语义分析->IR->优化->生成目标代码。

针对华为给出的方舟编译器的讲解,我们来看看方舟到底做了什么,以及推测一下方舟可能做了什么,或者方舟可以做什么。

1. 无需虚拟机运行

我们都知道,Java的字节码需要运行在Java虚拟机(JVM)上。JVM最重要的功能有两个:执行字节码和内存管理;我们分头来说说。

执行字节码

当JVM运行字节码的时候,会读取一条一条的指令,然后把指令翻译成当前机器的机器码并执行该操作,比如把当前栈上的两个数加起来然后再次压栈等等,这种方式叫做解释执行。

当JVM发现某一些指令经常会被执行到,每次翻译一遍会导致运行效率降低,于是JVM就把这些指令直接编译成当前机器的机器码,下次就直接执行机器码,不需要逐句翻译一遍,这就是JIT。

内存管理

写C代码的同学们,想要使用内存的时候,需要调用malloc函数动态申请一段内存,不再使用这段内存的时候,需要调用free函数进行内存释放,如果不释放,后果很严重。

而写Java代码的同学们就没有这个困惑,因为这件事被JVM承包了下来。JVM在执行字节码的过程中,会调用gc(garbage collection),gc帮我们释放不需要的内存。

方舟是怎么做的?

清楚了以上过程,我们就明白方舟编译器是怎么做的了。

既然JVM可以在运行过程中可以把字节码编译为机器码(JIT),那么为什么不能在运行字节码之前把字节码编译成机器码呢?没错,方舟就是这么做的,我们称之为AOT。

JVM的两大功能之一执行字节码就不需要了,那还有一个内存管理的功能怎么办呢?这个也好办,华为可以提供一个库,这个库实现gc所有的功能,我们称这个库为runtime。

以前我们使用JVM来运行一段字节码,现在这个流程变了,变成先把字节码(或者源程序)编译成机器码,然后带上runtime,直接运行在操作系统上,就不再需要VM了。

VM是不需要了,runtime是必不可少的,这个runtime需要处理包括但不限于以下几件事:创建对象,gc,函数调用,异常处理,锁,同步,多线程,反射。

都已经带上了这么多功能,那再带上一个解释器吧,多一个不嫌多。这些东西好像有些耳熟啊,好像安卓的ART也是这样的?我猜是的,由于Java语言本身和Java的运行时库等等一些历史原因,想推翻重来把这些东西都去掉,复杂度是很高的;所以安卓的爸爸谷歌也是在这些基础上进行修修补补。

当然,华为也可以选择不支持Java中一些动态的特性比如反射等功能,那么这个runtime是有可能简化的。到底方舟编译器和安卓已有的ART有什么不同,我们拭目以待。

2. 多语言联合优化编译器

这个很神奇对吧,C语言竟然可以和Java语言联合在一起编译。

我们知道C语言的代码编译过后是二进制文件,Java语言的代码编译过后是字节码;其实现代编译器在编译过程中有很多层中间表示,如果把源代码层看做最高层次,目标语言看成最低层次,编译过程中是逐层下降的,最后下降到目标层,和我们下楼梯是一样一样的,并不是自由落体对不对。

比如源代码经过编译器前端之后变成抽象语法树(AST),抽象语法树又可以转变为另一种更低层级的中间表示(IR),然后从IR再到目标层。

所以方舟可以定义一个中间表示(IR),把C语言和Java语言都先编译到这个中间表示层,然后在中间表示层做一系列的优化或者分析,再从中间表示层编译到机器码,这样就实现了多语言联合编译。

是不是把不同的语言编译到同一种IR上就万事大吉了呢?不是这样的!

方舟为什么要把多个语言放在一起编译?是好玩吗?当然不是!多个语言联合编译至少有以下几点好处:

减小跨语言调用开销

不同的语言之间,类型系统、调用规范、数据布局等等都不同,所以不同语言相互调用时有一些额外的开销。

我们知道Java调用C的接口规范叫做JNI,JNI帮助我们跨越语言的鸿沟,实现Java和C相互之间的调用。AOT在跨越语言鸿沟方面有一些好处,不同语言用同一个IR表示,runtime也是自己定制的,这不就是前店后厂嘛;

这样就有机会抹平不同语言之间的差异,比如可以让Java对象的数据布局和C中的对象数据布局保持一致,比如可以让C来兼容Java的类型系统(Java语言可以看做C++语言的一个子集)等等;提前抹平差异,使不同的东西保持一致,就不必在运行程序的时候再次进行转换,可以减小开销。

跨语言优化

一般情况下,不同的语言是分开编译的。而方舟编译器将不同的语言编译到同样的IR,便于将不同语言的代码联合起来进行全局优化,比如常量传播,函数内联等等。

当所有的代码都在同一IR上之后,还可以针对Java语言的特性做一些特定的静态分析,通过分析结果进行特定优化,比如可以针对不同种类的函数调用做de-virtualization等等。

什么是de-virtulization?简单来讲就是一些函数调用是通过类似于函数指针调用的方式间接调用,分析清楚这些间接调用可以把一些间接调用改成直接调用,而且是跨语言的直接调用,神奇吧!

3. 更高效的内存回收机制

内存回收是一个大问题,安卓应用卡顿部分原因就在内存回收。

前面提到,Java的内存回收工作被JVM接管了,写Java代码的同学并不需要手动进行内存回收,JVM会在“适当”的时候进行内存回收。

这个“适当”的时候通常是没有办法的时候,内存耗尽的时候;好比我有一张干净的桌子(堆内存),我们在桌子上面摆放了一些东西(消耗内存),当没有地方可以摆放新东西的时候,那就需要妈妈来帮忙收拾桌面了(内存回收)。

JVM中的GC如何判断哪些内存是需要的哪些内存是不需要的呢?这里面有个叫可达性分析的技术来帮我们判断哪些内存可以回收。

可达性分析的大致思想是,JVM运行过程中,创建了很多对象,这些对象之间有复杂的依赖关系,JVM先确定一些对象是根对象,从根对象出发,把所有直接依赖的对象和间接依赖的对象都标记出来,没有被依赖到的对象就不需要使用了,可以进行回收。

当有一段程序,在循环中大量创建新的对象,会造成内存快速耗尽,然后触发gc进行内存回收;频繁触发gc回收大量内存,这种现象叫做内存抖动,是造成安卓应用卡顿的一个很重要的原因。

写iOS应用的同学说我也没有管理内存,但是我写的应用就如丝般顺滑。是的,iOS应用较少发生内存抖动现象,使用了一种叫做引用计数的方法,其实这也是可达性分析技术里面的一种,Objective-C中称之为ARC。

引用计数是这样一种算法,每个对象都有一个计数器,当创建对象时候或者有其它的对象引用这个对象的时候,计数器数字也加1;当别的对象不再引用它时,计数器数字减1。

当计数器的数字回到0时,就将该对象回收。

还是刚才那个循环,在循环中创建大量对象,只要本次循环结束,就可以回收刚刚创建的对象,不会造成内存抖动。

对引用计数进行加1的动作好理解,这是用户自己写的代码,用户的代码中会写清楚什么时候创建对象,什么时候有了新的引用;对引用计数进行减1是谁来做的呢?

这个时候编译器就派上用场了,编译器可以分析对象的生命周期,在合适的地方插入这个对象减1的代码,这样在程序运行的时候引用计数就会加加减减。

方舟编译器的宣传材料中提到“随用随回收”,那么应该是使用了引用计数类似的技术,来减小内存抖动。当然,由于Java语言的问题,引用计数并不能解决所有问题,即使使用了引用计数,也需要gc来帮助回收内存。宣传材料中“回收时无需暂停应用”,应该是实现或者改进了Concurrent GC,来尽可能减小应用的停顿。

通过引用计数和改进GC,可以优化内存回收,减少内存回收的次数和减少暂停时间;既然有了统一的IR是不是可以天马行空一下,除了以上的东西可不可以做更多的一些优化呢?

前面提到引用计数可以解决局部变量用完马上回收的问题,而全局变量就搞不定了。那么方舟编译器有可能可以在这方面做一些文章,比如可以通过分析把一部分全局变量变成局部变量;再比如可以分析全局变量的生存周期,对全局变量也进行引用计数。总之,立即释放更多不需要使用的内存,就可以减少GC,减少卡顿。

好了,胡言乱语完了,我们还是等方舟编译器开源了,然后再一探究竟吧。

华为方舟编译器做了些什么,让安卓有了“丝滑”的感觉 ?相关推荐

  1. 华为的Java虚拟机_华为方舟编译器解析:提升安卓运行效率

    在今年发布P30的时候,华为还发布了一个名为"方舟"的编译器,但是很多人对方舟到底是什么其实有误解,这里我们就来详细说说.可以肯定的是,方舟并不是单独操作系统!而是安卓上的工具. ...

  2. 华为方舟编译器 PK 微软苹果谷歌编译器,到底谁胜出?

    记者 | 胡巍巍 受访者 | 刘新铭 出品 | CSDN(ID:CSDNnews) 近日,华为方舟编译器终于正式开源,兑现了在2019年8月开源的承诺. 与此同时,其代码不在GitHub,而是在自家开 ...

  3. 重磅!华为方舟编译器招募 2000 程序员!

    作者 | 胡巍巍 出品 | 程序人生(ID:coder_life) 华为北京研究所的食堂,周末也好热闹! 9月7日,笔者到华为北研所,参加华为方舟编译器(以下简称"方舟")的开源主 ...

  4. 华为方舟编译器开源!前华为人重磅解读!

    [CSDN 编者按]8月31日,华为方舟编译器正式开源.据华为内部人士表示,华为员工为了这次开源,连续30小时没有合眼. 早在在8月9日的华为开发者大会上,华为消费者业务CEO余承东,就宣布将在8月底 ...

  5. 支付宝澄清使用华为方舟编译器;三星苹果遭遇集体诉讼;PHP 7.4.0 beta4 发布 | 极客头条...

    快来收听极客头条音频版吧,智能播报由标贝科技提供技术支持. 「CSDN 极客头条」,是从 CSDN 网站延伸至官方微信公众号的特别栏目,专注于一天业界事报道.风里雨里,我们将每天为朋友们,播报最新鲜有 ...

  6. 华为方舟编译器开源,我命由我不由天!

    作者 | 胡巍巍出品 | CSDN(ID:CSDNnews)8月6日,华为开发者大会2019召开前夕,知名数码博主@菊厂搞机,发表了一篇名为<华为新贵!方舟编译器的荣光和使命>的长文,讲述 ...

  7. 华为方舟编译器是黑科技?

    在4月份,华为P30系列发布会上,华为消费者终端业务CEO余承东除了给消费者带来了万众期待的华为P30 Pro,还公布了一个全新的黑科技:华为方舟编译器.该编译器可以改善安卓应用编译效率,从原先的边解 ...

  8. 华为方舟编译器开源官网正式上线,并首次开放了框架源码!

    2019 年 8 月 31 日,华为方舟编译器开源官网正式上线,并首次开放了框架源码.方舟编译器对终端软件编译机制进行了架构级优化,将显著地提升用户体验. 官方网站: https://www.open ...

  9. 万字长文详解华为方舟编译器的荣光和使命

    本文由MO编辑部出品,文字超1万,查阅的资料多达上百万文字,并且与华为方舟编译器的专家做过深度访谈.其不仅解析了华为在编译器和手机系统方面做的多年准备,也向读者展现了波澜壮阔的软件产业发展史. 201 ...

最新文章

  1. buu [HDCTF2019]basic rsa
  2. BZOJ4653 尺取法 + 线段树
  3. [PHP] 现代化PHP之路:composer的镜像站设置
  4. 设置Web页面试用手机浏览器(iphone)
  5. 主动安全,新华三融合生态之力!
  6. 动态网页开发技术(二):Servlet
  7. LTE网络测试仪器和监控系统
  8. STM32CubeMX的安装
  9. iOS UISlider数值与滑块联动
  10. java提示没有main,有main方法却还是提示没有
  11. git 解决冲突(6)
  12. 把一个web项目改名后复制,再把改名后的web项目发布到tomcat,访问出现404错误的解决办法
  13. android百度地图poi路线规划,百度地图开发之poi检索,线路规划(示例代码)
  14. 企业微信登录不了怎么办 企业微信无法登录的原因及解决方法
  15. 三国志战略版360区S4服务器合并信息,三国志战略版s3赛季服务器合并与规则一览...
  16. zz:Android APP Monkey信息自动收集脚本
  17. ubuntu解压和压缩tar文件
  18. python字典怎么处理_Python字典的处理
  19. 世界顶级的程序员大佬都有谁?
  20. 算法 2.2 合并链表 LA 和 LB

热门文章

  1. integer conversion resulted in a change of sign
  2. 使用BDE数据库引擎的应用软件出现Insufficient disk space的解决方法
  3. z390 m.2 接口插上sata 硬盘后,机械硬盘不识别;HDD 硬盘不识别;z390 m.2和 SATA 硬盘安装组合;
  4. C语言实现画爱心(两种方式画法)
  5. 智能耳机测试软件,智能可穿戴设备有哪些?解析可穿戴设备的作用和测试
  6. php本地文件包含 截断,php远程文件包含截断问题
  7. 为了下半年的「双 11」,阿里的「赚钱机器」开始冲刺
  8. MyBatis中设置事务自动提交
  9. 从产业互联网的角度,解读360智慧商业发布“春雨计划”
  10. 企业生产中,APS系统有哪些具体应用场景?