1.什麼是JIT編譯器前端
JIT編譯器,即Just-In-Time Compiler(即時編譯器)。JIT編譯屬於動態編譯(即運行時編譯)的一種,與之對應的是靜態編譯(AOT)。java
2.爲何要用JIT編譯器算法
咱們都知道,一般經過javac將程序源代碼編譯(前端編譯,與語言有關,機器無關)成字節碼,JVM經過解釋字節碼將其翻譯成對應的機器指令,逐條讀入,逐條解釋翻譯。很顯然,通過解釋執行,其執行速度必然會比可執行的二進制字節碼程序慢不少,這就是傳統的解釋器(Interpreter)的功能。爲了解決這種效率問題,引入了JIT技術。緩存
3.JIT編譯器是如何工做的函數
JIT 工 做 原 理 圖優化
Java程序仍是經過解釋器進行解釋執行,當JVM發現某個方法或代碼塊運行特別頻繁的時候,就會認爲這是「熱點代碼」(Hot Spot Code),而後JIT會把部分「熱點代碼」翻譯成本地機器相關的機器碼,並進行優化,而後把翻譯後的機器碼緩存起來,下次能夠直接使用。spa
HotSpot虛擬機中內置兩個JIT編譯器:Client Compiler和Server Compiler,分別用在客戶端和服務端,目前主流的HotSpot虛擬機默認是採用解釋器和其中一個編譯器直接配合的工做方式。線程
當JVM執行代碼時,它並不會當即編譯代碼,緣由有兩點:翻譯
■ 若是這段代碼自己只會被執行一次,那從本質上看,編譯器就是在浪費精力,由於將代碼翻譯成Java字節碼(解釋器解釋執行)相對於編譯這段代碼並執行代碼來講,要快不少。對象
■ 最優化,當JVM執行某一方法或執行遍歷的次數越多,就會更瞭解代碼結構,那麼JVM在編譯代碼時就作出了相應的優化。
咱們能夠看本身機器上安裝的JDK中JIT是哪一種模式:
其中,不管是Clent仍是Server,都是mixed mode,即解釋器和編譯器搭配使用的混合模式。
注:Client啓用的是代號爲C1的編譯器,是輕量級編譯器;Server啓用的是代號是C2的編譯器,時重量級編譯器。
4.熱點檢測
想要觸發JIT編譯,就要先識別出熱點代碼,目前主要的熱點代碼識別方式是熱點探測,有兩種方式:
■ 基於採樣的方式探測:週期性檢測各個線程的棧頂,發現某個方法常常出如今棧頂,就認爲是熱點方法。好處是簡單,缺點是沒法精確確認一個方法的熱度,容易受線程阻塞等緣由的干擾。
■ 基於計數器的熱點探測:採用這種方法的虛擬機會爲每一個方法,甚至代碼塊創建計數器,統計方法的執行次數,某個方法超過閥值就認爲是熱點方法,觸發JIT編譯。
在HotSpot虛擬機中使用的是基於計數器的熱點探測,它爲每一個方法準備了兩個計數器:方法調用計數器和回邊計數器。
■ 方法調用計數器:記錄一個方法被調用次數。
■ 回邊計數器:記錄方法中的for或while的運行次數的計數器。
5.全部對象都分配到堆上嗎?
在《深刻理解Java虛擬機》中有這樣一段話:「隨着JIT編譯器的發展和逃逸分析技術的逐漸成熟,棧上分配、標量替換優化技術將會致使一些微妙的變化,全部的對象分配到堆上也漸漸不那麼絕對了」。這是因爲在編譯期間,JIT會對代碼作不少優化,其中有一部分優化的目的就是減小內存堆分配的壓力,其中一項重要的技術叫作逃逸分析。
逃逸分析是目前Java虛擬機中比較前言的優化技術,這是一種能夠有效減小Java程序中同步負載和內存堆分配壓力的跨函數全局數據流分析算法。經過逃逸分析,HotSpot編譯器可以分析出一個新的對象的引用的使用範圍,從而決定是否要將這個對象分配到堆上。其基本行爲就是分析對象動態做用域:當一個對象在方法中被定義後,能夠被外部方法調用,則稱爲方法逃逸。
對於定義在方法內部的對象,不會逃逸到其方法外部,通過JIT的逃逸分析,就會對其內存分配進行優化。結果就是,若是循環定義1萬個對象,大多數會分配到棧上,減輕堆的壓力。