方舟編譯器需要安裝嗎?
看了下面不少朋友的回答,大部分都答偏了。
首先亮結論:方舟編譯器不會安裝在消費者的手機上。
下面來從以下幾個維度說明原因。
1. 編譯器是什么?首先要明確的是:編譯器是一個通用概念,它不是僅僅針對手機,最早它的對象是計算機。
編譯器就相當于一個翻譯官,它的作用就是將高級語言(比如Java)編寫的代碼,轉換成在操作系統(tǒng)(比如微軟的Windows 10)上可以直接運行的二進制程序(比如QQ.exe)。
1.1 為什么要轉換成二進制程序,才能在計算機上運行呢?因為計算機系統(tǒng)的本質就是一堆開關,通過“開關”狀態(tài)的改變——閉、合,來觸發(fā)相應物理特性的變化(電平變化、磁性變化等),達到相互通信的等價效果。而閉、合這兩種狀態(tài)正好可以對應1和0兩個數(shù),這樣計算機系統(tǒng)就和表示1和0的二進制聯(lián)系起來了。
無論是CPU,還是內存、鼠標、鍵盤、硬盤、光盤……它們都基于上述基本原理,筆者的專欄撰寫了不少文章,詳細介紹了背后的實現(xiàn)方式。
1.2 編譯器 vs 解釋器現(xiàn)實世界中,常見的翻譯有兩種形式:一種是一次性全部翻譯,比如翻譯的文學著作;
另一種是同聲傳譯,同聲傳譯是一種實時翻譯,主講人說一句或者幾句,翻譯者同步翻譯出來。
回到編譯的世界,前者對應編譯器,后者對應解釋器。
編譯器說白了就是一次性把所有的代碼翻譯成目標平臺的二進制,然后運行的時候,直接全速運行。
解釋器則是邊翻譯邊運行:讀一條或者幾條語句,翻譯成對應的二進制,然后運行這一部分;接著再讀接下來的一條或者幾條語句,翻譯成對應的二進制,然后再運行接下來的這一部分……以此類推。
從上面的描述可以看出,從最終的運行效率上看,編譯器的方式應該是遠遠超過解釋器的,畢竟前者是一次性得到所有的二進制,這樣運行的時候就是一股腦地往前沖;而解釋器則是邊翻譯邊運行,速度上比應該是要慢不少。
除此之外,因為編譯器是一次性翻譯,所以它可以縱觀全局,找出可以復用、優(yōu)化的部分,然后加以綜合,便于得到全局最優(yōu)的二進制結果;而解釋器由于是邊翻譯邊運行,是一種局部行為,不利于進行全局把控、優(yōu)化。
傳統(tǒng)Java的運行是基于JVM(Java虛擬機)的,JVM其實就是一個加強版的解釋器。它引入了JIT及其變種技術。這個技術名詞上看上去高大上,其實原理說白了很簡單:
我們都知道現(xiàn)實世界都遵循“二八原則”,即:任何領域,少部分的占比貢獻或者占據(jù)了絕大部分的價值或資源。這個原則在代碼領域也同樣適用:
有一些代碼比較“熱門”,會被不斷地重用或者調用,比如Java語言里熱門的類、方法等。這樣在翻譯它們的時候,把它們緩存起來,這樣解釋器再次遇到這些代碼的時候,就不用重新再翻譯一遍,直接從緩存里取出翻譯的結果來就好了。
當然,為了取得更好的優(yōu)化結果,我們還可以將顆粒度做得更小,比方說我們可以把方法中被頻繁調用的循環(huán)語句的翻譯結果緩存起來。
1.3 為什么Java要基于解釋器技術的JVM呢?既然JVM基于解釋器技術,天生就比較慢,那為什么Java還要執(zhí)著于這種模式20多年呢?或者換句話說,自從Java1995年左右誕生,直到現(xiàn)在,除了華為,難道就沒有其他公司想到拋棄JVM,直接采用編譯器技術,直接將Java代碼編譯成原生二進制呢?
基于虛擬機運行的高級語言,比如Java,從代碼到最終的二進制執(zhí)行,其實就是兩個階段:
第一個階段:代碼->中間代碼(字節(jié)碼)
第二個階段:中間代碼(字節(jié)碼)->二進制
有小伙伴就會挑戰(zhàn)了:為什么非要搞出一個中間代碼(字節(jié)碼)呢?這個其實來自Java這樣的高級語言的市場營銷口號:Wrtie once,Run everywhere(一次編寫、到處運行)。
通過Java編譯器(Javac)將代碼編譯成標準的中間代碼(字節(jié)碼)之后,就可以將它部署到任何硬件平臺上,只要該硬件平臺上有對應的解釋器將它在運行時翻譯成對應的目標二進制,然后就可以運行了。
通過這種策略,只要每一個硬件平臺上有對應的解釋器,保證從中間代碼(字節(jié)碼)翻譯到二進制的運行效果都一樣,那么程序員只用寫一套代碼就完事了。
更重要的是:只要對中間代碼(字節(jié)碼)的格式、含義等進行了明確的規(guī)定、形成規(guī)范,那么開發(fā)對應硬件平臺上的解釋器,這個工作就可以交給不同的專業(yè)公司去做,從社會分工上也極大提高了效率:
一些公司專注寫上層應用程序代碼,一些公司專注開發(fā)第一個階段(代碼->中間代碼)的編譯器,一些公司專注制定中間代碼(字節(jié)碼)的規(guī)范,另一些公司可以專注開發(fā)不同硬件平臺上的解釋器——有3家硬件平臺,就可以交給3家公司去做……
說得再通俗一點就是:創(chuàng)造了更多的就業(yè)崗位、大家都有飯吃:)
用流行的行話來說,就是建生態(tài)。
如果干掉JVM,那么:
從專注制定中間代碼(字節(jié)碼)規(guī)范的公司角度看:
我的飯碗沒了!而且我最生氣,在之前的生態(tài)中,我的話語權最高,現(xiàn)在我直接被華麗麗地無視了!而且在現(xiàn)實世界中,制定規(guī)范的公司往往就是發(fā)明和營銷該語言的公司,它的感受可想而知。
從專注開發(fā)第一個階段(代碼->中間代碼)編譯器的公司和專注開發(fā)第二個階段(中間代碼->二進制)解釋器的公司角度看:
沒我啥事了,我的飯碗沒了——就算干掉JVM的新技術中仍然有中間代碼的變種,那我也得重新熟悉新變種,之前開發(fā)的東西都得改,這都是成本和風險。
在華為之前,歷史上是否有嘗試干掉JVM的公司呢?
答案是肯定的。
Java在1995被SUN發(fā)明出來之后,運行效率一直被詬病,1997年前后Java JIT技術開始被追捧。Symantec在打敗了Borland等競爭對手、取得了JIT 編譯器表面上的優(yōu)勢之后,立刻把重點放在了開發(fā)直接把 Java中間代碼(字節(jié)碼)編譯成原生應用程序的原生Java 編譯器。Symantec 成功開發(fā)出了這個原生Java編譯器之后,加入到當時它最熱銷的集成開發(fā)環(huán)境Visual Café 中,成為一項吸引人的功能。不過很快地這個功能卻引起了許多Java 使用者的批評,因為他們認為這違反了Java“一次編寫、到處運行”的精神,如此一來廠商必須為每一個不同的平臺開發(fā)原生Java 編譯器,這會造成Java 應用程序在不同的平臺執(zhí)行的反應不一致的現(xiàn)象,又陷入C/C++語言開發(fā)的應用程序在不同的平臺表現(xiàn)不一的相同問題。后來連發(fā)明Java的SUN也不贊成這種做法,當然這是因為SUN想力推自己的HotSpot編譯器技術。因此原生Java編譯器在風行了一陣短暫的時間之后就不再吸引人注意了。
下面再講一個哪怕沒有干掉JVM,只是魔改了JVM也被“修理”的例子。
比爾蓋茨在挖到了Borland公司的首席架構師、被業(yè)內稱為“編譯器之神”的Anders Hejlsberg之后,在1996年11月發(fā)布了Microsoft Visual J++,該Java編譯器的性能超越了同期的所有競爭對手。
但是這款編譯器魔改了SUN制定的JVM規(guī)范,引入了很多自有創(chuàng)新,比如:
(1)對象模型創(chuàng)新:Sun的JVM的對象模型將“對象頭”與對象的實例數(shù)據(jù)分開存放,而Microsoft Visual J++把兩者放在了一起。
(2)使用指針而不是基于句柄的引用:因為Microsoft Visual J++基本上是用C/C++加上匯編寫的,可以直接方便地使用指針來高效訪問數(shù)據(jù),而SUN是用Java來開發(fā)JVM的,只能使用句柄。
(3)垃圾收集機制創(chuàng)新:Microsoft Visual J++采用的分代的GC,大幅領先于當時的Sun JVM使用的不分代的GC。
(4)對象同步創(chuàng)新:SUM JVM使用的是哈希表來存放同步對象的映射,每次都需要先將句柄轉換成key去查表;而微軟采用的是它們在操作系統(tǒng)設計中常用的手法,直接在對象頭中放一個同步塊的指針,指針訪問一步到位。
(5)RNI:直接采用COM技術訪問本地接口,而不需要通過SUN定義的接口做二次轉換。
Microsoft Visual J++推出之后也很快受到了所有Java 開發(fā)工具以及支持Java平臺廠商的全面圍剿。他們害怕Microsoft對Java市場的入侵,會讓其他廠商再次無法生存。之后連SUN也開始領軍圍攻 Microsoft,因為SUN除了害怕Microsoft 會慢慢地主宰Java 平臺和標準之外, 還發(fā)現(xiàn) Microsoft正在很有技巧地逐步破壞Java語言和標準,例如Microsoft Visual J++便提供了許多非標準的Java用法并且很明顯地把 Microsoft Visual J++綁死在Windows 平臺,破壞 Java 的"一次編寫、到處運行"的美夢。
通過上面兩個20多年前的經典案例,不難看出:干掉JVM這件事,早有公司做過技術上的成功嘗試,但是最終都沒能在商業(yè)和市場上成功。這里面最關鍵的阻力在于:動了Java的品牌擁有者(以前是SUN,現(xiàn)在是收購了SUN的Oracle)的蛋糕,而它是Java的親爹,掌握了“血統(tǒng)的純正權”和“生態(tài)主導權”。根據(jù)現(xiàn)有的游戲規(guī)則,即便不是干掉JVM,哪怕是提供一個獨立的JVM,也必須通過對應的TCK(Java兼容性測試)認證,才能被“合法化”。
2. 方舟編譯器的優(yōu)勢是什么?這個其實在前文已經表達得比較清楚了:直接編譯出原生二進制,運行速度快。
但是帶來的風險在上一個章節(jié)也揭示得很清楚了,這是現(xiàn)在大部分人忽視的地方。
既然干掉JVM的潛在風險不小,那么為什么仍然要力推方舟編譯器呢?筆者分析如下:(1)因為方舟編譯器本質上是一個通用的編譯器框架,該框架理論上可以支持所有的語言,而不僅僅是Java。極端情況下,遭遇類似Symantec或者Microsoft當年受到的打擊,也不是“滿盤皆輸”。
(2)方舟編譯器這個框架,從實現(xiàn)上仍然采用了中間代碼的技術,所以傳統(tǒng)生態(tài)中,專注開發(fā)第一個階段(代碼->中間代碼)編譯器的公司和專注開發(fā)第二個階段(中間代碼->二進制)解釋器的公司仍然可以在方舟生態(tài)中找到新的位置。關鍵在于配合怎樣的生態(tài)政策和投資政策來吸引它們轉型。
(3)基于方舟編譯器的開放框架和中間語言技術,可以創(chuàng)造新的編程語言,這樣也可以在極端情況下形成“編程語言的備胎”(這個有點杞人憂天了)。
(4)方舟配合鴻蒙等OS,撐大生態(tài)喇叭口,增加供應鏈上的自主控制點。
3. 方舟編譯器的使用對象是誰?它的使用對象是App開發(fā)者或者App運營商(App應用商城)。當他們使用方舟編譯器將使用Java語言編寫的App編譯成目標手機硬件平臺的二進制之后,就上架到App應用商城,供手機消費者下載。
4. 手機如何被方舟編譯器加速?不是手機被加速,而是App被加速。但這個加速是在上架App應用商城、被手機消費者下載之前就完成了。并沒有什么額外“魔法”在消費者的手機上。
5. 方舟編譯器的更多細節(jié)關于方舟編譯器的更多細節(jié),可以關注筆者的頭條號以及頭條號付費專欄,里面有全方位的技術干貨解讀。