自適應收集器
在第一篇:關於JVM 的垃圾收集(一)中談到過幾種垃圾收集的算法,然而我們的 JVM 啟動之後並不要求徹頭徹尾的死板的使用一種垃圾收集算法,固定的算法參數。因為某種情況下某些垃圾收集算法工作得更好,而別外一些收集算法在另外的情況下工作得更好,所以自適應的垃圾收集技術應運而生。自適應算法監視堆中的情形,並且對應的調整為合適的垃圾收集技術。或能是換一種垃圾收集算法,或者是調整當前算法參數,或者把堆劃分為子堆,同時在不同的子堆中使用不同的算法。
簡述火車算法
垃圾收集一般都會停止整個程序的運行來查找和收集垃圾對象,它們可能在程序執行的任意時刻暫停,並且暫停的時間也無法確定。垃圾收集也可能使得程序對事件響應遲鈍,無法滿足實時系統的要求。如果一種垃圾收集算法可能導致用戶可察覺的到的停頓或者使得程序無法適合實時系統的要求,這種算法被稱作破壞性。垃圾收集算法的還有一個基本目標是使本質上的破壞性盡可能少,如果可能的話,盡可能消除這種破壞性。
達到(或試圖達到) 非破壞性垃圾收集的方法是使用漸進式收集算法。漸進式收集器就是不試圖一次性發現並回收所有不可觸及的對象,而是每次發現並回收一部分。因為每次只有堆的一部分執行垃圾收集,因此理論上說每次收集會持續更短的時間。保證這個最短時間接近某一個時長,就可以讓 Java 虛擬機適合實時環境,也就可以消除用戶可察覺的垃圾收集停頓,這可稱之為限時漸近時垃圾收集。
漸進式收集器通常是分代收集的,大部分調用中,都是收集堆的一部分。大部分對象都是短命的,利用這一點,分代收集器在年幼子堆中比在年長子堆中更活躍。因為除了最高壽的子堆(成熟對象空間) 外,每個子堆中都可以給定一個最大尺寸,分代收集器大體上可以保證在一個最大時間內漸進地收集所有對象(最高壽的除外)。成熟對象空間無法給定最大尺寸,因為其中的對象不適合時沒個去處。
於是針對成熟對象空間提供限定時間的漸時收集,Richard Hudson 和 Eliot Moss 提出了火車算法,目前正用於 Sun 公司的 Hotspot 虛擬機中。該算法詳細說明了分代收集的垃圾收集器的成熟對象空間的組織。大體有些車廂、火車、火車站的概念,對於該算法的此處不作進一步說明了。
finalize() 方法
一個 Java 對象可以擁用終結方法:這個方法在垃圾收集器釋放對象之前必須運行。但這麼一個終結方法的引入並不明智,會使得 JVM 的垃圾收集的工作變得更得雜,所以別用它。
因為,存在終結方法時,垃圾收集器必須在每次在收集時執行一些額外的步驟。首先第一遍掃描時,垃圾收集器檢測出不再被引用的對象,然後看那些對象上是否聲明了終結方法,有則執行。當執行了所有的終結方法後,垃圾收集器必須再次從根節點或是需要執行終結的對象開始檢測不再被引用的對象,這稱作第二遍掃描。這個步驟是必要的,因為終結方法可能“復活”了第一遍掃描標記的對象。最後,垃圾收集器才能釋放那些在第一遍和第二遍掃描中發現的都沒有被引用的對象。
如果第一遍掃描標記不再引用的對象的終結方法運行過了,而後這個對象被自己或其他對象的終結方法復活了,稍後再次被收集時,執行過的終結方法就不能再執行了。同時終結方法何時被執行也是無法預測的。