那天去面試,面試官問我JVM垃圾回收,我是有備而來,上來就是一個可達性分析算法,然后就是一個復制算法,標記-清理,標記-整理,以及幾個常見的垃圾回收器
詳情見:https://www.cnblogs.com/KeleLLXin/p/13752680.html 。
按照傳統面試,我已經回答完了,面試官突然問我GC Root有哪些? 不是存活的有依賴的都可以做GC Root嗎?我大意了,回答的不是很好,所以今天來整理一下。
在Java語言中,GC Root主要包括以下幾類元素:
1、虛擬機棧中引用的對象
比如:各個線程被調用的方法中使用到的參數、局部變量等。
2、本地方法棧內JNI(通常說的本地方法)引用的對象
3、方法區中類靜態屬性引用的對象
比如:Java類的引用類型靜態變量
4、方法區中常量引用的對象
比如:字符串常量池(string Table) 里的引用
5、所有被同步鎖synchronized持有的對象
6、Java虛擬機內部的引用。
基本數據類型對應的Class對象,一些常駐的異常對象(如:
NullPointerException、OutOfMemoryError) ,系統類加載器。
7、反映java虛擬機內部情況的JMXBean、JVMTI中注冊的回調、本地代碼緩存等
8、除了這些固定的GCRoots集合以外,根據用戶所選用的垃圾收集器以及當前回收的內存區域不同,還可以有其他對象“臨時性”地加入,共同構成完整GC Roots集合。比如:分代收集和局部回收(Partial GC)。
如果只針對Java堆中的某一塊區域進行垃圾回收(比如:典型的只針對新生代),必須考慮到內存區域是虛擬機自己的實現細節,更不是孤立封閉的,這個區域的對象完全有可能被其他區域的對象所引用,這時候就需要一並將關聯的區域對象也加入GC Roots集
合中去考慮,才能保證可達性分析的准確性。
小技巧:由於Root采用棧方式存放變量和指針,所以如果一個指針,它保存了堆內存里面的對象,但是自己又不存放在堆內存里面,那它就是一個Root
注意
如果要使用可達性分析算法來判斷內存是否可回收,那么分析工作必須在
一個能保障一致性的快照中進行。這點不滿足的話分析結果的准確性就無法保證。
這點也是導致GC進行時必須“Stop The World"的一個重要原因。
即使是號稱(幾乎)不會發生停頓的CMS收集器中,枚舉根節點時也是必須要停頓的。