注:主要參考自《分佈式java應用:基礎與實踐》《深刻理解Java虛擬機(第二版)》html
一、兩種執行方式:java
注意:分佈式
查看當前機器默認是client模式仍是server模式,使用:"java -version"命令,以下ide
其中,mixed mode表示"解釋執行+編譯執行"的混合模式性能
二、解釋執行優化
查看 第三章 類文件結構與javap的使用 中的inc()方法的執行spa
或者查看《深刻了解java虛擬機(第二版)》P272-P275線程
三、編譯執行3d
四、C1優化code
說明:關於所有的優化技術列表,查看《深刻理解java虛擬機(第二版)》P346-P347
只作少許性能開銷比高的優化,佔用內存少,主要的優化包括:
4.一、方法內聯、冗餘消除、複寫傳播、消除無用代碼
4.1.一、方法內聯
方法內聯含義:假設方法A調用了方法B,把B的指令直接植入到A中。
static class B{ int value; final int get() { return value; } } public void foo() { y = b.get(); //do something z = b.get(); sum = y + z; }
說明:在上述代碼中,b是B的一個實例。
方法內聯以後,
public void foo() { y = b.value; //do something z = b.value; sum = y + z; }
方法內聯的條件:
方法內聯的地位:
4.1.二、冗餘消除
冗餘消除:如上邊的兩個b.value冗餘(前提,在do something部分沒有對b.value進行操做,這也是咱們在作優化以前須要先收集數據的緣由)
假設在do something部分沒有對b.value進行操做,進行冗餘消除後,
public void foo() { y = b.value; //do something z = y; sum = y + z; }
4.1.三、複寫傳播
固然,在冗餘消除後,JIT對上述的代碼進行分析,發現變量z沒用(能夠徹底用y來代替),進行"複寫傳播"以後,
public void foo() { y = b.value; //do something y = y; sum = y + y; }
4.1.四、無用代碼消除
在"複寫傳播"後,發現"y=y"是無用代碼,因此能夠進行"無用代碼的消除"操做,消除以後,
public void foo() { y = b.value; //do something sum = y + y; }
須要說明的是,這裏的"無用代碼的消除"是在前三部優化的基礎上來作的,而javac編譯中"語義分析"部分的"無用代碼的消除"是直接消除一些直接寫好的代碼(例如:if(false){})
4.二、類型繼承關係分析、去虛擬化
public interface Animal { public void eat(); } public class Cat implements Animal{ public void eat() { System.out.println("cat eat fish"); } } public class Test{ public void methodA(Animal animal){ animal.eat(); } }
首先分析Animal的整個"類型繼承關係",發現只有一個實現類Cat,那麼在methodA(Animal animal)的代碼就能夠優化爲以下,
public void methodA(Animal animal){ System.out.println("cat eat fish"); }
可是,若是以後在運行過程當中,"類型繼承關係"發現Animal又多了一個實現類Dog,那麼此時就不在執行以前優化編譯好的機器碼了,而是進行解釋執行,即以下的"逆優化"。
逆優化:
當編譯後的機器碼的執行再也不符合優化條件,則該機器碼對應的部分回到解釋執行。
eg.好比"去虛擬化",若是編譯以後,發現類的實現方法多於一種了,此時就要執行"逆優化"
五、C2優化
進行了大量優化,佔用內存多,適用於服務端程序,對於C2優化,除了具備C1的優化措施後,還有不少優化。
逃逸分析(輔助):
開啓:-XX:+DoEscapeAnalysis
根據運行情況來判斷方法中的變量是否會被方法或外部線程所讀取,若不會,此變量是不逃逸的。基於此,C2在編譯時會作:
5.一、標量替換
含義:將一個java對象打散,根據程序,將該對象中的屬性做爲一個個標量來使用。
Point point = new Point(1,2); System.out.println("point.x:" + point.x + ",point.y:" + point.y); //do after
若在//do after中(即前邊兩句代碼以後的全部代碼中)再沒有其餘代碼訪問"point對象"了,則將"point對象"打散並進行標量替換,
int x = 1; int y = 2; System.out.println("point.x:" + x + ",point.y:" + y);
好處:
5.二、棧上分配
含義:肯定一個方法的變量不會逃逸出當前方法以外(即該變量不會被其餘方法引用),則該變量能夠直接分配在棧上,隨方法執行結束,棧幀消失,該變量也消失,減輕GC壓力。
好處:
5.三、同步削除
含義:肯定一個方法的變量不會逃逸出當前線程以外(即該變量不會被其餘線程使用),則對於該變量的同步策略就消除掉,以下,
synchronized(cat){ //do xxx }
若cat不會逃逸出當前線程,則同步塊能夠去掉,以下,
//do xxx
總結:
解釋器:
JIT編譯器:
注意: