溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JVM內(nèi)存增強(qiáng)之逃逸分析怎么使用

發(fā)布時間:2022-09-20 09:45:15 來源:億速云 閱讀:152 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“JVM內(nèi)存增強(qiáng)之逃逸分析怎么使用”,在日常操作中,相信很多人在JVM內(nèi)存增強(qiáng)之逃逸分析怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JVM內(nèi)存增強(qiáng)之逃逸分析怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

概念

逃逸分析一種數(shù)據(jù)分析算法,基于此算法可以有效減少 Java 對象在堆內(nèi)存中的分配。 Hotspot 虛擬機(jī)的編譯器能夠分析出一個新對象的引用范圍,然后決定是否要將這個對象分配到堆上.

 當(dāng)一個對象在方法中被定義后,對象只在方法內(nèi)部使用,則認(rèn)為沒有發(fā)生逃逸。

 當(dāng)一個對象在方法中被定義后,它被外部方法所引用,則認(rèn)為發(fā)生逃逸。

//對象發(fā)生了逃逸,不會在棧上分配,有可能導(dǎo)致GC STW
public StringBuffer append(String s1, String s2) {
 StringBuffer sb = new StringBuffer();
 sb.append(s1);
sb.append(s2);
 return sb;
}
//對象未發(fā)生逃逸
public String append(String s1, String s2) {
 StringBuffer sb = new StringBuffer();
 sb.append(s1);
 sb.append(s2);
 return sb.toString();
}

建議:開發(fā)中能在方法內(nèi)部應(yīng)用對象的,就盡量控制在內(nèi)部

逃逸分析參數(shù)設(shè)計(jì)

在 JDK 1.7 版本之后, HotSpot 中默認(rèn)就已經(jīng)開啟了逃逸分析,如果使用的是較早的

版本,開發(fā)人員則可以通過:

? 選項(xiàng)“ -XX:+DoEscapeAnalysis" 顯式開啟逃逸分析。

? 通過選項(xiàng)“ -XX:+PrintEscapeAnalysis" 查看逃逸分析的篩選結(jié)果。

使用逃逸分析

編譯器可以對代碼做如下優(yōu)化

1.棧上分配:將堆分配轉(zhuǎn)化為棧分配。如果一個對象在方法內(nèi)創(chuàng)建,要使指向該對象的引用不會發(fā)生逃逸,對象可能是棧上分配的候選

/**
* 棧上分配測試(-XX:+DoEscapeAnalysis)
* -Xmx128m -Xms128m -XX:+DoEscapeAnalysis -XX:+PrintGC
*/
public class ObjectStackAllocationTests {
 public static void main(String[] args) throws InterruptedException {
 long start = System.currentTimeMillis();
 for (int i = 0; i < 10000000; i++) {
 alloc();
 }
 long end = System.currentTimeMillis();
 System.out.println("花費(fèi)的時間為: " + (end - start) + " ms");
 // 為了方便查看堆內(nèi)存中對象個數(shù),線程 sleep
 TimeUnit.MINUTES.sleep(5);
 }
 private static void alloc() {
 byte[] data = new byte[10];//未發(fā)生逃逸
 }
}

2.同步鎖消除:

我們知道線程同步是靠犧牲性能來保證數(shù)據(jù)的正確性,這個過程的代價會非常高。程序 的并發(fā)行和性能都會降低。JVM 的 JIT 編譯器可以借助逃逸分析來判斷同步塊所使用的鎖對象是否只能夠被一個線程應(yīng)用?假如是,那么 JIT 編譯器在編譯這個同步塊的時候就會取消對這部分代碼上加的鎖。這個取消同步的過程就叫同步省略,也叫鎖消除

public class SynchronizedLockTest {
 public void lock() {
 Object obj= new Object();
 synchronized(obj) {
 System.out.println(obj);
 }
}

3.標(biāo)量替換分析

所謂的標(biāo)量(scalar)一般指的是一個無法再分解成更小數(shù)據(jù)的數(shù)據(jù)。例如,Java 中 的原始數(shù)據(jù)類型就是標(biāo)量。相對的,那些還可以分解的數(shù)據(jù)叫做聚合量(Aggregate),Java 中的對象就是聚合量,因?yàn)樗梢苑纸獬善渌酆狭亢蜆?biāo)量。在 JIT 階段,如果經(jīng)過逃逸分析,發(fā)現(xiàn)一個對象不會被外界訪問的話,那么經(jīng)過 JIT 優(yōu)化,就會把這個對象分解成若干個變量來代替。這個過程就是標(biāo)量替換。

public class ObjectScalarReplaceTests {
 public static void main(String args[]) {
 long start = System.currentTimeMillis();
 for (int i = 0; i < 10000000; i++) {
 alloc();
 }
 long end = System.currentTimeMillis();
 System.out.println("花費(fèi)的時間為: " + (end - start) + " ms");
 }
 private static void alloc() {
 Point point = new Point(1,2);
 }
 static class Point {
 private int x;
 private int y;
 public Point(int x,int y){
 this.x=x;
 this.y=y;
 }
 }
//對于上面代碼,假如開啟了標(biāo)量替換,那么 alloc 方法的內(nèi)容就會變?yōu)槿缦滦问?
private static void alloc() {
     int x=10;
     int y=20;
 }

alloc 方法內(nèi)部的 Point 對象是一個聚合量,這個聚合量經(jīng)過逃逸分析后,發(fā)現(xiàn)他并沒有逃逸,就被替換成兩個標(biāo)量了。那么標(biāo)量替換有什么好處呢?可以大大減少堆內(nèi)存的占用。因?yàn)橐坏┎恍枰獎?chuàng)建對象了,那么就不再需要分配堆內(nèi)存了。標(biāo)量替換為棧上分配 提供了很好的基礎(chǔ)。 

FAQ

1.什么是逃逸分析?

可以有效減少 Java 對象在堆內(nèi)存中的分配壓力和同步負(fù)載的算法

2.逃逸分析有什么優(yōu)勢、劣勢?

逃逸分析是需要消耗一定的性能去執(zhí)行分析的,所以說如果方法中的對象全都是處于逃逸狀態(tài),那么就沒有起到優(yōu)化的作用,從而就白白損失了這部分的性能消耗

到此,關(guān)于“JVM內(nèi)存增強(qiáng)之逃逸分析怎么使用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI