從JVM角度看,有這幾種優化手段:java
棧上分配:
同步省略
標量替換
這幾個優化手段須要JVM配置以外,寫代碼時仍是須要配合的點,要不JVM優化也不會起做用,拜拜提供了優化手段而你不用面試
代碼優化點太多了,我覺淂仍是叉開來好些好理解一些......post
棧上分配具體內容看:JVM 面試題【中級】,我就再也不寫一遍了性能
方法內部變量寫的好一些,仔細一些以實現棧上分配的確有很大優點,這裏跑個例子測試
public class Max {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
newValue();
}
long endTime = System.currentTimeMillis();
System.out.println("Time:" + (endTime - startTime));
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void newValue() {
Dog dog = new Dog();
}
}
複製代碼
-Xms256m -Xmx256m -XX:-DoEscapeAnalysis -XX:+PrintGCDetails
[GC (Allocation Failure) [PSYoungGen: 65536K->761K(76288K)] 65536K->769K(251392K), 0.0016895 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 66297K->713K(76288K)] 66305K->721K(251392K), 0.0023094 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Time:91
複製代碼
-Xms256m -Xmx256m -XX:+DoEscapeAnalysis -XX:+PrintGCDetails
Time:7
複製代碼
你們別看測試用例方法是執行1000萬次,就意味沒有實際意義啦,你們寫的程序,分分鐘你覺得方法執行的少嗎,能不能作到棧上分配堆性能是及其有意思的,差距你們都看到了吧優化
神轉折來啦 (/// ̄皿 ̄)○~ 這是《深刻理解JVM虛擬機裏的原話》
spa
逃逸分析的技術99年就出現了,一直到JDK1.6 Hotspot 纔開始支持初步的逃逸分析,即使到如今這項技術仍未成熟,還有很大的改進餘地。不成熟的緣由是逃逸分析的計算成本很是高,甚至不能保證帶來的性能優點會高於計算成本,在實際應用中,尤爲是大型應用中反而發現逃逸發分析可能出現不穩定的狀態。直到JDK7時才默認開啓這項技術,服務模式的java程序才支持3d
上面例子效果明顯,更多緣由是由於下面會說的標量替換
,沒看到內存快照嘛,即使開啓逃逸分析以後,Dog對象在堆內存中仍是有很是多的對象存在,這和理論差距仍是滿大的日誌
懶得打字了,你們看圖吧: code
典型的例子:
public void test() {
Dog dog = new Dog();
synchronized (dog) {
System.out.println(dog);
}
}
複製代碼
對於上面這個方法,JIT 動態編譯器雖然會幫咱們自動把鎖消除了,可是在這是在運行階段纔會優化的,編譯成字節碼時仍是能看到鎖指令的
另外雖然有JIT優化,可是相比咱們直接不寫鎖,優化以後的性能仍是不如的,你們最好仍是這樣寫,性能更好一些:
public void test() {
Dog dog = new Dog();
System.out.println(dog);
}
複製代碼
java 中:
標量:
是指一個沒法再被分解成更小的數據的數據,好比基礎數據類型聚合量:
相對的就是那些還能夠再分解的,好比對象就是-XX:+EliminateAllocations
JDK7開始默認是開啓的在JIT階段,通過逃逸分析後,若是方法內對象符合棧上分配的規則,那會這個對象在棧上就會以標量的形式存儲,能夠進一步節省分配對象的操做
好比一個對象:
public class Dog extends Max {
public int age = 10;
public String name = "AA";
}
複製代碼
通過標量替換後,一個Dog對象會以這種方式存儲在局部變量表裏:
public void test() {
// 一個 Dog 對象會變成下面這樣
int age = 10;
String name = "AA";
}
複製代碼
標量替換爲棧上分配提供了很好的基礎 (⊙﹏⊙)
標量替換你要是在 JVM 配置裏面關了,那棧上分配就無論用了,標量替換、棧上分配
這2個必須都得設置才能起做用
PS:想罵娘,深度越深的技術,只是點都是這樣拔出蘿蔔帶出泥,一茬接一茬,應接不暇,越看越暈,要是資料再補全,跳着來,尼瑪想死的心都有 (〃>目<)