一、怎麼判斷一個對象爲垃圾
1.在我們的jvm中有一個root根節點。root根節點會引用對象,如果一個對象做可達性分析能夠到root根節點,則表示該對象不是垃圾(1,2,3,4),但是如5.6兩個對象雖然兩者間有相互引用,但是到root根節點不可達,則表示爲垃圾,將會被垃圾收集器回收。
2.哪些是root根節點。
類加載器、Thread、虛擬機棧的本地變量表、static成員、常量引用、本地方法棧變量等,這些都是root根節點,因爲這些在程序運行過程中,怎麼都不會被垃圾收集器回收,而其他對象是否是垃圾則對這些做可達性分析。
二、常用算法
1.標記清除
該算法分爲兩個階段“標記”、“清除”。第一次先標記出哪些是垃圾,第二次將標記的對象進行清除(銷燬)。
缺點:效率不高、標記和清除兩個過程效率都不高
產生空間碎片,因爲被標記的對象在空間物理上並不一定是連續的,當清除完之後,我們剩下存活的對象在物理上也不一定是連續的,這就意味着這些不連續的對象之間有很大一部分空間將利用不到,則是空間碎片。
2.複製算法
首先將內存分爲大小相等的兩塊,每次只使用其中的一塊,當第一塊中的內存用完時,做可達性分析,將存活的對象複製到另一塊去,然後對第一塊內存做一次全部清理。
優點:效率高,不會產生空間碎片
缺點:空間利用率不高。只有50%。
3.標記整理
和標記清除算法類似,但是在第一階段標記之後,並不是自己進行清除,而是將存活的對象移至空間的一段,然後對端邊界以外的內存直接進行一次清理
優點:不會產生空間碎片
缺點:標記整理效率不高,很耗時。
三、jvm使用
1.算法使用
jvm中young區使用的是複製算法,因爲在young區一般對象存活的時間不長,產生垃圾的速度比較快,所以採用效率較高的算法。
old區主要使用標記清除或標記整理,因爲一般在old區的對象存活時間比較長,不需要經常做垃圾回收,所以採用效率不高,但空間利用較高的算法
四、對象分配
1.對象優先在Eden區分配。
2.如果是大對象,可以直接進入老年代。什麼纔是大對象。-XX:PretenureSizeThreshold 超過這個參數的值則表示爲大對象。
3.長期存活的對象進入老年代,什麼纔是長期存活的對象。
-XX:MaxTenuringThreshold 經歷了這個參數值的minor gc之後可進入老年代
-XX:+PrintTenuringDistribution 輸出在Survivor區對象的年齡情況,相當於日誌
-XX:TargetSurvivorRatio 通過一個公式計算sutvivor區的對象是需要進入old區。