首先我們要明白優化代碼,並不是建立在java的源碼之上的。而是建立在代碼的中間表達是或者機器碼上面。
公共子表達式消除
如果一個表達式E已經出現過了。而且下面出現的E的所有變量值都沒有發生改變,那就可以優化。
如 a=b*c+r+c*b
這裏b*c和c*b是一樣的。所以可以變成 a=e+r+e
數組邊界檢查消除
我們知道java是一門動態安全的語言。訪問數組的時候,會進行上下界限的檢查。是否每一次都真的有必要檢查呢?
其實,只要在編譯的時候根據數組的大小來判斷是否出界就行了。 特別是循環數組的時候,只要區間一直在0到數組最大下標直接。在編譯是判斷。那麼在運行期間就不必去檢查。
方法內聯
它是編譯器最重要的優化手段之一。方法內聯後,其他方法才能基於它。
我們知道,調用其他方法要有出棧入棧等操作。影響效率。但是如果把這個方法放到代碼當中,那就不用調用。當然就會快。
但是,這是非虛方法纔好。(非虛方法在編譯的時候就可以知道是哪個方法,如私有方法,靜態方法等)。
內聯後,還有一個逃生門,因爲你虛擬機不知道這個方法的接受者的繼承關係會發生變化。也就是說,這個方法可能不是惟一的。那就拋棄已經編譯的代碼,退回到解釋狀態。
虛方法,有個內聯緩存。調用到這個方法的哪個具體實現,那就存這個。
逃逸分析
如果一個對象會被外部方法調用,那就叫做方法逃逸
如果一個對象會被其他的線程訪問到,那就叫做線程逃逸
棧上分配
一個對象不會方法逃逸和線程逃逸,那就一個把對象分配到棧上。我們知道,垃圾回收的效率是比較緩慢的。但是如果對象能隨着方法的結束而自動銷燬。那垃圾回收壓力就會小很多
同步消除
線程的同步是一個相對耗時的過程。如果如果一個對象沒有線程逃逸,那就可以關掉線程同步。
標量替換
標量是值無法在分解的數據。如int long 等。如果一個對象不會方法逃逸,而且這個對象可以被拆散的話。我們用到他的成員變量就不用再調用對象的成員變量。直接替換爲相應的標量。