1.java堆中幾乎放着所有對象的實例,那么什么樣子的對象才是可以被回收的呢?
1.1.引用計數法:
給對象添加一個引用計數器,當有地方引用的時候,計數器就+1,引用失效就-1;任何時候當計數器為0,那么這個對象就是可以被回收的。該方法實現簡單,效率也高,但是並沒有被主流的虛擬機采用,因為很難解決對象互相循環引用問題。
1.2.可達性分析算法
這個的基本思想就是通過一系列的“GC Roots”作為對象的起點,從這些節點開始向下搜索,節點所走過的路徑稱為引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連的話,則證明此對象是不可用的。

那些可以作為GC Roots節點呢? 一般來說類加載器、Thread、虛擬機棧的本地變量表、static成員、常量引用、本地方法棧的變量等等。
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 對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。
但是並不是和對象一樣不使用了就會必然被回收。
