GC機制總結

1.爲什麼要使用垃圾收集?

 

   字面是說是“垃圾收集”,更精確點就是“內存回收”,在一個對象不再被程序引用時,它所佔用的堆空間就可以回收,以便分配給新對象使用。而且除了釋放不再被引用的對象外,垃

圾收集器還要處理堆碎塊(堆碎塊是在正常的程序運行時產生的),因爲新的對象分配了空間,不再被引用的對象被釋放,所以堆內存的空閒位置介於活對的對象之間,而請求分配新對象時可能不得不增大堆空間,因爲雖然總的空閒空間是夠的,但堆中沒有連續的空閒空間放得下新對象。

 

   上面是垃圾收集的作用,其好處在於:1)提高了工作效率,在一個沒有垃圾收集機制的語言下編程,程序員還要花時間來解決難以捉摸的內存問題

                                                2)幫助程序保持完整性,因爲程序員不可能因爲失誤錯誤地釋放內存而導致jvm崩潰

 

2.垃圾收集器怎麼知道對象不再被引用?

  

    垃圾檢測通常是通過建立一個根對象的集合並且檢查從這些根對象開始的可觸及性來實現。可觸及就是正在執行的程序可以訪問到的根對象和某個對象之間存在引用路徑。

    區分活動對象和垃圾的兩個基本方法是引用計數跟蹤。

 

3.引用計數收集器是怎麼判定對象爲垃圾的?

  

   引用計數的原理是:堆中第一個對象都有一個引用計數,當有一個對象被創建時,這個對象的引用計數被置爲1。當有其他變量被賦值爲這個對象的引用時,計數加1;當這個對象的引用超過了生存期或被設置爲新的值,計數減1;當計數爲0時,對象被認爲是垃圾,將被回收;

   這種方法的早已過時,主要缺陷是:他無法檢測出循環引用(即兩個或多個對象互相引用),例如:父對象有一個對子對象的引用,子對象又反過來引用父對象,這時計數永遠不可能爲0。

 

4.跟蹤收集器又是怎麼一回事?

 

   跟蹤就是對對象設置標記,通過一個從根結點開始的對象引用圖追蹤對象,在這個過程中對遇到的對象打上標記,當追蹤結束時沒有被打上標記的就是無法觸及的,從而可以被回收。

 

5.怎麼處理堆碎塊?

 

   一般處理堆碎塊有以下幾種收集器:

  

   1.壓縮收集器:把活動的對象都推到堆的一端,從而使另一端出瑞一個大的連續空閒區,所有被移動的對象的引用也被更新,指向新的位置;爲了簡便,更新被移動的對象引用時通過一個間接引用層,因爲不直接引用堆中的對象而對象的引用實際上指向一個對象句柄表的話不用改變引用指向的位置,但損失了部分性能。

 

   2.拷貝收集器:把所有的活動的對象移動到一個新的區域,在這個過程中,活動對象被緊挨着佈置從而消除原本它們在舊區域的空隙。一般的拷貝收集算法是——停止並拷貝,在這個方法中堆被分爲兩個區域,任何時候都只使用其的一個區域。對象在同一個區域分配,直到這個區域滿了爲止;這時程序中止,堆被遍歷,遍歷到的活動對象被拷貝到另外一個區域,完成後程序繼續執行,如此循環;這種方法的代價是:對於指定大小的堆來說需兩倍大小的內存。

下圖是“停止並拷貝”算法的垃圾收集堆的圖形描述:第一張圖中,堆的下半部分沒有被使用,上半部分被對象零散的填充;2圖是上半部分逐漸被填充,3圖中上半部分被填滿,這時程序中止,垃圾收集器開始工作,從根結點開始追蹤活動對象圖,當遇到活動對象時就拷貝到堆的下半部分,每一個都緊挨着,如4圖;如此打循環:

   3.按代收集的收集器

     簡單的停止拷貝收集器的缺點在於:第一次收集,所有的活動對象都要被拷貝,而程序中一般都有以下特點:

     1)大多數程序創建的大部分對象都具有很短的生命期;

     2)大多數程序都創建一些具有非常長生命週期的對象;

     簡單的停止拷貝收集器每次都把那些生命週期長的對象來回拷,浪費了時間;按代收集器通過把對象按照壽命來分組,更多的收集那些年幼的對象,當一個年幼對象經過幾次收集後仍然存活,那就將它提升爲壽命更高的一代,從而對這個對象的收集頻率就減少了,幫命越長的收集頻率就越小;

 

  4.自適應收集器:看這個收集器的名字,顧名思義:根據不同的情況選擇不同的垃圾收集技術;

 

6.什麼是火車算法

 

    由於垃圾收集時一般會停止程序,如果停止的時間長得讓用戶注意到而不滿意,那就說明這種算法存在破壞性,爲了減少這種破壞性而採用漸進式收集算法(每次回收一部分),通常漸進式收集器都是按代收集器,而火車算法就是爲了在成熟空間空間(最高壽的那個年齡層)提供限定時間的漸進收集。

   火車算法把成熟對象空間劃分爲固定長度的內存塊,算法每次在一個塊中單獨執行,每一個塊屬於一個集合,塊就是“車廂”,集合就是“火車”,成熟對象空間就是“火車站”;就如車廂一樣,塊在一個集合中有序的;集合也被排序,就像火車站中的火車按軌道排列一樣,如下圖:

對象從更年輕的年齡層的子堆中進入成熟對象空間都會被附加到任何已存在的火車中或者爲他們專門創建一列或多列火車。

     每一次執行火車算法的時候,它不是收集最小數字的火車中的最小數字車廂,就是收集整列最小數字的火車,算法首先檢查指向最小數字火車中任何車廂的引用,如果不存在任何來自最小數字火車以外的引用指向它內部包含的對象,那麼整個火車都是垃圾,回收整個火車;如果不都是垃圾,那麼將注意力放在火車中最小數字車廂上,首先把所有被最小數字車廂外部的車廂引用的對象轉移到其他車廂去,之後任何保留在車廂內的對象都是沒有引用的,可以被回收;

而保證整列火車中沒有循環的數據結構的關鍵是算法如何移動對象:

1)如果對象被成熟對象空間的其他火車引用,對象不被轉移到引用它的那列火車中去;

2)然後轉移過後的對象被掃描,查找對原車廂的引用,發現的任何被外用的對象都被轉移到引用它的火車中去;

3)新被轉移的對象也被掃描,這個過程不斷重複,直到沒有任何來自其他火車的引用指向正被收集的車廂;

4)如果接收對象的火車沒有空間了,那麼算法會創建新的車廂,並附加到那列火車的尾部;

 

7.終結

   java中一個對象可以擁有終結方法:這個方法是垃圾收集器在釋放對象前必須運行的。這個方法使垃圾收集器要做的工作更加複雜,因爲垃圾收集器必須檢查它所發現的不再被引用的對象是否存在終結方法——finalize();還得記住一點:是垃圾收集器運行對象的終結方法。

 

8.GC中對象的六種可觸及狀態

   1.強可觸及:對象可以從根結點不通過任何引用對象搜索到

   2.軟可觸及:對象不是強可觸及的,但是可以從根結點開始通過一個或多個(未被清除的)軟引用對象觸及

   3.弱可觸及:對象既不是強可觸及也不是軟可觸及的,但是從根結點開始可以通過一個或多個弱引用對象觸及

   4.可復活的:對象既不是強可觸及、軟可觸及,也不是弱可觸及,但是仍然可能通過執行某些終結方法復活到這幾種狀態之一

   5.影子可觸及:不上以上任何可觸及狀態,也不能通過終結方法復活,並且它可以從根結點開始通過一個或多個影子引用對象觸及(影子引用不會被垃圾收集器清除,由程序明確地清除

   6不可觸及:就是已經準備回收的狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章