1、引言
在座的各位程式員們,10月24號,今天還有沒有是坐在公司加班的?
小編估計肯定有,誰讓我們是程式員,就好比如保衛國家的戰士們,總是奮戰在戰場的前線,來守護老百姓的生活安寧,
不管咋樣,小編還是祝賀同胞們節日快樂,永無BUG、永遠青春、永不脫發~~~
2、想一想
在小編剛開始學習Java語言的時候,然后知道了JVM,之前老師一直說Java中的實體物件就存盤在JVM中的堆區,
先給大家上一張JVM的記憶體模型圖,這圖應該很熟悉吧,應該對每一塊干什么用的多多少少也有了解個大概,

過了幾年,Java中的實體物件全部都是存盤在堆區的概念,已經被小編我深深的烙印在心中,
還記得小編在面試的時候,遇到過一個類似的問題:
面試官:你知道Java的實體物件是存盤在JVM中哪個區域么?
小編:堆區,
面試官:那假設在方法中new了一個百萬個物件,也還是全部存盤在堆區嗎?
那么關鍵的地方來了,當初對于年少無知的小編來說,哪會想那么多,就死腦筋認為只要是實體物件就只會存盤在堆區中,
如果小伙伴你們也不知道答案,那么帶著這個問題,來看實際操作一波吧,
public class Test_1 {
public static void main(String[] args) {
for (int i=0;i < 10000;i++){
create();
}
while (true);
}
public static void create(){
Test_1 test = new Test_1();
}
}

在代碼中,回圈了1w次,通過HSDB工具(HSDB可以查看JVM在運行時資料區的內容),很明顯能看出,在堆區中,確實存在1w個Test_1物件,那么現在改成把回圈改成100w,再看看,

這下好了,count并沒有達到100w個,最初小編想的是是不是被GC回收了,然后列印GC日志也沒有發現,
那么問題來了,剩下的物件跑哪兒去了???
3、看一看
其實這里就涉及到一個知識點,叫做:逃逸分析,默認逃逸分析是開啟的,我們先把逃逸分析關閉掉,再試試,


把逃逸分析關閉之后,通過查看物件,這下總算有100w個了,
4、什么是逃逸分析?
用官方的話來說,逃逸分析是一種確定指標動態范圍的方法,可以分析在程式的哪些地方可以訪問到指標,這里的指標可以理解成java的實體物件的參考地址,而指標動態范圍可以理解為物件的訪問修飾符(public、private等),
上面那樣的解釋估計很多小伙伴都不懂,用代碼來舉個例子,
在start方法中,new了一個Test_1物件,很明顯test_1這個物件是不是只能在start()方法中使用,其他地方都不能夠使用,
這種物件就可以理解為不逃逸物件,因為它不能被其他地方訪問到,
public class Test_1 {
public static void main(String[] args) {
start();
}
public static void start() {
Test_1 test_1 = new Test_1();
}
}
那現在將start方法改一下,把test_1這個物件回傳出去,那么這個物件就是可以理解為一個逃逸物件,因為它被回傳出去了,只要是呼叫了start這個方法,就可以拿到這個物件,被其他地方訪問到,
或者說當一個實體物件的參考指標被多個方法或執行緒參考時,我們稱這個指標發生了逃逸,
public static Test_1 start() {
Test_1 test_1 = new Test_1();
return test_1;
}
最后通過這種逃逸和不逃逸的現象,來進行分析,就稱之為:逃逸分析,
5、堆疊上分配
堆疊上分配就是基于逃逸分析這個分析,最后分析出來的一種優化方式,最大的好處應該是減少gc的壓力,把那些不逃逸的物件分配在堆疊上,這樣逃逸分析完后可以確定哪些變數可以分配在堆疊上,堆疊的分配比堆快,性能好,
這樣就像本文一開始演示的一樣,100w物件并沒有全部在堆中,而把逃逸分析關閉了,就都放在堆中了,
逃逸分析可以通過這個引數控制,-XX:+/-DoEscapeAnalysis,+就是表示開啟,-就是表示關閉,
下次如果再遇到問物件是不是全部放在堆上堆這種問題,可不要直接說都放在堆上,
當然堆疊上分配只是其中一種優化,還有包括標量替換、鎖消除等等,在逃逸分析的時候,如果你定義的物件的方法上有同步鎖,但在運行時,卻只有一個執行緒在訪問,此時逃逸分析后的機器碼,會去掉同步鎖運行,
看著小編1024還在碼文章的份上,點個贊,點個贊,點個贊~~~~~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/190437.html
標籤:其他
上一篇:re模塊常用方法
