都2020年10月24了,你可能還不知道那些JVM的祕密

2020-10-25 13:00:27

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還在碼文章的份上,點個贊,點個贊,點個贊~~~~~~