java虛擬機(九)編譯是如何優化代碼的

首先我們要明白優化代碼,並不是建立在java的源碼之上的。而是建立在代碼的中間表達是或者機器碼上面。

公共子表達式消除

如果一個表達式E已經出現過了。而且下面出現的E的所有變量值都沒有發生改變,那就可以優化。

如  a=b*c+r+c*b

這裏b*c和c*b是一樣的。所以可以變成 a=e+r+e

數組邊界檢查消除

我們知道java是一門動態安全的語言。訪問數組的時候,會進行上下界限的檢查。是否每一次都真的有必要檢查呢?

其實,只要在編譯的時候根據數組的大小來判斷是否出界就行了。 特別是循環數組的時候,只要區間一直在0到數組最大下標直接。在編譯是判斷。那麼在運行期間就不必去檢查。

方法內聯

它是編譯器最重要的優化手段之一。方法內聯後,其他方法才能基於它。

我們知道,調用其他方法要有出棧入棧等操作。影響效率。但是如果把這個方法放到代碼當中,那就不用調用。當然就會快。

但是,這是非虛方法纔好。(非虛方法在編譯的時候就可以知道是哪個方法,如私有方法,靜態方法等)。

內聯後,還有一個逃生門,因爲你虛擬機不知道這個方法的接受者的繼承關係會發生變化。也就是說,這個方法可能不是惟一的。那就拋棄已經編譯的代碼,退回到解釋狀態。

虛方法,有個內聯緩存。調用到這個方法的哪個具體實現,那就存這個。

逃逸分析

如果一個對象會被外部方法調用,那就叫做方法逃逸

如果一個對象會被其他的線程訪問到,那就叫做線程逃逸

棧上分配 

一個對象不會方法逃逸和線程逃逸,那就一個把對象分配到棧上。我們知道,垃圾回收的效率是比較緩慢的。但是如果對象能隨着方法的結束而自動銷燬。那垃圾回收壓力就會小很多

同步消除

線程的同步是一個相對耗時的過程。如果如果一個對象沒有線程逃逸,那就可以關掉線程同步。

標量替換

標量是值無法在分解的數據。如int long 等。如果一個對象不會方法逃逸,而且這個對象可以被拆散的話。我們用到他的成員變量就不用再調用對象的成員變量。直接替換爲相應的標量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章