jvm(4)---垃圾回收(哪些對象能夠被回收)

1.java堆中幾乎放着全部對象的實例,那麼什麼樣子的對象纔是能夠被回收的呢?java

1.1.引用計數法:算法

給對象添加一個引用計數器,當有地方引用的時候,計數器就+1,引用失效就-1;任什麼時候候當計數器爲0,那麼這個對象就是能夠被回收的。該方法實現簡單,效率也高,可是並無被主流的虛擬機採用,由於很難解決對象互相循環引用問題。spa

1.2.可達性分析算法線程

這個的基本思想就是經過一系列的「GC Roots」做爲對象的起點,從這些節點開始向下搜索,節點所走過的路徑稱爲引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連的話,則證實此對象是不可用的。對象

那些能夠做爲GC Roots節點呢? 通常來講類加載器、Thread、虛擬機棧的本地變量表、static成員、常量引用、本地方法棧的變量等等。blog

1.3 finalize()方法(只會被調用一次)隊列

即便在可達性分析算法中不可達的對象,也並不是是「非死不可」的,這時候它們暫時處於「緩刑」階段,要真正宣告一個對象死亡,至少要經歷再次標記過程。內存

標記的前提是對象在進行可達性分析後發現沒有與GC Roots相鏈接的引用鏈。字符串

1.3.1. 第一次標記並進行一次篩選。虛擬機

篩選的條件是此對象是否有必要執行finalize()方法。

當對象沒有覆蓋finalize方法,或者finzlize方法已經被虛擬機調用過,虛擬機將這兩種狀況都視爲「沒有必要執行」,對象被回收。

1.3.2. 第二次標記

若是這個對象被斷定爲有必要執行finalize()方法,那麼這個對象將會被放置在一個名爲:F-Queue的隊列之中,並在稍後由一條虛擬機自動創建的、低優先級的Finalizer線程去執行。這裏所謂的「執行」是指虛擬機會觸發這個方法,但並不承諾會等待它運行結束。這樣作的緣由是,若是一個對象finalize()方法中執行緩慢,或者發生死循環(更極端的狀況),將極可能會致使F-Queue隊列中的其餘對象永久處於等待狀態,甚至致使整個內存回收系統崩潰。

finalize()方法是對象脫逃死亡命運的最後一次機會,稍後GC將對F-Queue中的對象進行第二次小規模標記,若是對象要在finalize()中成功拯救本身----只要從新與引用鏈上的任何的一個對象創建關聯便可,譬如把本身賦值給某個類變量或對象的成員變量,那在第二次標記時它將移除出「即將回收」的集合。若是對象這時候還沒逃脫,那基本上它就真的被回收了。

1.4 如何判斷一個常量是廢棄常量

假如在常量池中存在字符串 "abc",若是當前沒有任何String對象引用該字符串常量的話,就說明常量 "abc" 就是廢棄常量,若是這時發生內存回收的話並且有必要的話,"abc" 就會被系統清理出常量池。

1.5 如何判斷一個類是無用的類

1.該類全部的實例都已經被回收,也就是 Java 堆中不存在該類的任何實例。

2.加載該類的 ClassLoader 已經被回收。

3.該類對應的 java.lang.Class 對象沒有在任何地方被引用,沒法在任何地方經過反射訪問該類的方法。

可是並非和對象同樣不使用了就會必然被回收。

相關文章
相關標籤/搜索