在初學JVM的時候,咱們每每會對這部分感到迷惑:網上很多博客介紹的五花八門,像引用計數算法、串行、並行、併發算法等,他們到底算不算垃圾回收算法,算的話又和基本的那幾個算法有什麼關係呢?(PS:其實若是認真看過書的話,就不會疑惑了,由於書裏邊介紹的很清晰),下邊咱們來理一下這些算法的關係: java
在咱們回收一個對象以前,咱們首先要搞明白的一點是這個對象是否是已經死了(沒有用了),而對於java程序而言,當一個對象再也不被引用,那麼他就死了(沒被引用就沒法被正常訪問了)。爲實現這個判斷,可使用兩種算法實現:引用計數和可達性分析。
引用計數實現計較簡單,每一個對象對應一個引用計數器,當有被引用的時候就+1,引用被釋放的時候-1,這樣當該值爲0時,則對象已死。這一算法有個問題就是:當出現相互引用(相似於多線程死鎖的狀況)的時候,對象雖死,可是計數器卻不爲0。
可達性分析也叫作根節點搜索算法,其實現是根據圖的搜索(固然,圖的搜索其實就是樹遍歷),JVM首先建立一個GC Root的根節點,全部建立的對象在存活的時候都能根據引用關係找到到達該根節點的路徑,若是找不到路徑,則說明該對象已死。這一算法不只解決了引用計數的缺陷,並且不用每一對象都維護一個計數器,目前最經常使用的HotSpot虛擬機就採用該算法。 算法
所謂算法,就是在時間、空間、實現複雜度這三者的互博中尋求一個最優的實現。而幾種垃圾回收算法也是在這幾個方面各有側重。
標記-清除算法分爲兩個階段:先對回收對象進行標記,而後統一回收。這種思路很簡單,實現也很容易,可是卻頭兩個缺點:一是標記、清除效率都很低,二是會產生碎片化,清除後空出來的空間是零散的。
複製算法是將內存空間分爲兩個部分,對象同時只存在其中一個裏邊,當回收時將存活對象複製到另外一區便可,這樣就不用再進行清除了(直接覆蓋便可),還不會產生生碎片。以前提到分代回收中Eden去的survivor便使用該算法。可是該算法缺點也很明顯,有一半空間浪費了,典型的空間換時間。
標記-整理算法是標記-清除的升級版,上邊說到,清理過程也是效率很低的,那麼該算法第二步就不進行清理,而是將對象向前移動,覆蓋該回收的區域,這樣整理後就不會產生碎片了。年老代通常採用該算法。
該部分可參考。 服務器
首先咱們要提到一點是,垃圾回收因爲涉及對內存的整理,要求整理時內存狀態是不能被程序改變的,也就是Stop-The-World模式下進行。當gc時間過長時,程序會出現長時間停頓,這對於響應較高的應用是不可接受的。所以,在結合線程後實現了不一樣方式的收集器,以知足不一樣需求。
多線程
本次JVM相關算法介紹完畢,下次將重點放在JVM監控、調優等方面,因爲我的沒有太多實踐經驗,這部分主要會整理相關資料。 併發