-
前言
總所周知,jvm的垃圾收集算法一般包括標記、清除、整理三個階段,最近在看了有關於垃圾收集的標記算法,記錄一下自己的理解。
垃圾收集中標記算法有兩種:一種是引用計數法,一種是根搜索算法。
-
引用記數法
引用計數法非常容易理解,jvm為每一個對象設立一個引用計數器,當該對象被引用時,計數器就加一,引用取消時則減一。
當jvm開始gc時,jvm判斷該對象的引用計數器是否為0,若為0則標記為可清除對象。
引用計數器有個致命的缺點是無法解決循環依賴問題,這也導致這個算法被棄用。
如下圖所示,當對象A中有對B的引用,對象B中也有對A的引用,兩者之間形成循環依賴。
除此之外,還有一個point引用了對象A,此時程序中還有point這個指針能夠使程序到達這兩個對象,
一旦point引用取消,我們就會丟失對這兩個對象的控制,同時引用計數器未到達0,所以對象一直存在在堆中,JVM不能進行回收,從此造成內存泄漏。
-
根搜索算法
根搜索算法是目前大部分JVM所使用的標記算法。
根搜索算法會以根對象集合中的根對象出發,進行自上往下的搜索,與根對象直接連接或間接連接的對象都可以被搜索。
當JVM無法到達某個對象時,它會被標記為可清除對象。
根對象集合指的是:
- JAVA棧中的對象引用
- 本地方法棧的對象引用
- 運行時常量池中的對象引用
- 方法區中的類靜態屬性的對象引用
- 類對應的唯一數據類型的Class對象(這句話有點抽象,實際上每個類都有一個Class對象用於表示這個類在運行時被JVM加載的相關信息,如類名、方法、屬性等)
可以使用ClassName.class、實例化對象.class、Class.forName(),獲取該類的Class對象
根搜索算法的過程