new關鍵字發生了什麼系列補充(Java內存結構與垃圾回收問題)

前言

學習了之前的一些知識之後,爲了給自己學習之前的問題做簡單的解答

0x01 如何判斷垃圾

首先通過可達性分析算法分析(沒有gc roots),然後在jvm中進行標記,finalize方法中可以取消標記(重新獲取gc roots)。

判斷垃圾這個階段是在發生gc的時候,垃圾收集器需要根據該方式確定垃圾並回收。

0x02 對象在堆內存中如何分配

1、是否在TLAB上分配
2、jvm參數檢查,內存需要分配在哪裏(常見垃圾收集器將堆內存繼續劃分)
3、新生代分配(棧上有引用,堆中有實例數據,方法區有Class對象,常量池有常量)
4、內存不足,發生gc垃圾回收
5、對象基礎信息初始化等

0x03 對象在堆內存中如何回收

不同的垃圾收集器回收算法不同,新生代的垃圾通常採用複製算法,老年代採用標記-清除算法或標記-整理算法。

不同的算法可能也會導致不同的問題,比如cms中的標記-清除算法以及cms獨特的實現機制,可能在一次gc中觸發另一次gc

0x04 什麼時候發生gc

情況一:創建新對象的時候,由於內存不足,需要一次gc

情況二:前一次gc可能觸發另一次gc,比如cms老年代收集失敗

0x05 什麼時候發生minor gc

分配對象實例內存時,Eden空間內存不足

0x06 什麼時候發生full gc

情況一:發生minor gc前,cms垃圾收集器要求老年代進行一個擔保,可能導致垃圾回收

情況二:直接分配在老年代的時候,如果老年代內存不足,可能觸發

情況三:hotspot將方法區放在永久代實現,如果需要加載更多類,則觸發

情況四:System.gc()方法

0xFF 總結

垃圾收集就是內存回收,爲了程序能繼續運行,需要將程序運行期間產生的內存垃圾清空,否則再大的內存也不夠程序執行。如何高效的在程序執行的期間也能進行垃圾的收集就是一件很重要的事情,因爲編寫java程序不需要主動去回收內存垃圾,所以jvm替我們完成這項工作。

因此,jvm進一步抽象了內存空間,對內存空間進一步劃分,是爲了更好的收集內存。雖然jvm可能不同,垃圾收集器也不同,但是java在內存結構的劃分給了一份規範。所以其他jvm實現廠商在此規範上進行開發。雖然不同的jvm有不同的實現,但是在大方向上,基本都是能夠形成統一。

瞭解垃圾回收雖然不能幫助我們寫出更好的代碼,但是在瞭解之後我們寫代碼會更慎重,比如設置Map的大小能減少gc等

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章