Java編譯原理

做爲一個程序員,咱們常掛在嘴邊的"編譯"是指把各個語言寫出來的文件轉換成JVM可識別文件的一個過程,如將.java程序編譯成java字節碼文件,即 .class文件,其實對於一個計算機來講,字節碼文件並不能被識別,須要把字節碼轉換成機器指令,纔是計算機層面的編譯,這個過程是虛擬機作的。以上兩個「編譯」過程整合纔是真正的編譯原理,以下圖:前端

根據完成的任務不一樣,能夠將編譯器的組成部分劃分爲前端(Front End)與後端(Back End)。java

前端編譯主要指與源語言有關但與目標機無關的部分,包括詞法分析、語法分析、語義分析與中間代碼生成。
後端編譯主要指與目標機有關的部分,包括代碼優化和目標代碼生成等。程序員

咱們能夠把將.java文件編譯成.class的編譯過程稱之爲前端編譯。把將.class文件翻譯成機器指令的編譯過程稱之爲後端編譯。後端

前端編譯

咱們所熟知的javac的編譯就是前端編譯。除了這種之外,咱們使用的不少IDE,如eclipse,idea等,都內置了前端編譯器。主要功能就是把.java代碼轉換成.class代碼緩存

後端編譯

JVM 經過解釋字節碼將其翻譯成對應的機器指令,逐條讀入,逐條解釋翻譯。很顯然,通過解釋執行,其執行速度必然會比可執行的二進制字節碼程序慢不少。這就是傳統的JVM的解釋器(Interpreter)的功能。爲了解決這種效率問題,引入了 JIT 技術。eclipse

JAVA程序仍是經過解釋器進行解釋執行,當JVM發現某個方法或代碼塊運行特別頻繁的時候,就會認爲這是「熱點代碼」(Hot Spot Code)。而後JIT會把部分「熱點代碼」翻譯成本地機器相關的機器碼,並進行優化,而後再把翻譯後的機器碼緩存起來,以備下次使用。ide

HotSpot虛擬機中內置了兩個JIT編譯器:Client Complier和Server Complier,分別用在客戶端和服務端,目前主流的HotSpot虛擬機中默認是採用解釋器與其中一個編譯器直接配合的方式工做。優化

當 JVM 執行代碼時,它並不當即開始編譯代碼。首先,若是這段代碼自己在未來只會被執行一次,那麼從本質上看,編譯就是在浪費精力。由於將代碼翻譯成 java 字節碼相對於編譯這段代碼並執行代碼來講,要快不少。第二個緣由是最優化,當 JVM 執行某一方法或遍歷循環的次數越多,就會更加了解代碼結構,那麼 JVM 在編譯代碼的時候就作出相應的優化。idea

在機器上,執行java -version命令就能夠看到本身安裝的JDK中JIT是哪一種模式:線程

上圖是個人機器上安裝的jdk1.8,能夠看到,他是Server Compile,可是,須要說明的是,不管是Client Complier仍是Server Complier,解釋器與編譯器的搭配使用方式都是混合模式,即上圖中的mixed mode。

熱點檢測

上面咱們說過,要想觸發JIT,首先須要識別出熱點代碼。目前主要的熱點代碼識別方式是熱點探測(Hot Spot Detection),有如下兩種:

一、基於採樣的方式探測(Sample Based Hot Spot Detection) :週期性檢測各個線程的棧頂,發現某個方法常常出險在棧頂,就認爲是熱點方法。好處就是簡單,缺點就是沒法精確確認一個方法的熱度。容易受線程阻塞或別的緣由干擾熱點探測。

二、基於計數器的熱點探測(Counter Based Hot Spot Detection)。採用這種方法的虛擬機會爲每一個方法,甚至是代碼塊創建計數器,統計方法的執行次數,某個方法超過閥值就認爲是熱點方法,觸發JIT編譯。

在HotSpot虛擬機中使用的是第二種——基於計數器的熱點探測方法,所以它爲每一個方法準備了兩個計數器:方法調用計數器和回邊計數器。

方法計數器。顧名思義,就是記錄一個方法被調用次數的計數器。

回邊計數器。是記錄方法中的for或者while的運行次數的計數器。

相關文章
相關標籤/搜索