天天看點

Java垃圾收集學習筆記

(1)除了釋放不再被引用的對象,垃圾收集器還要處理 堆碎塊 。請求配置設定新對象時可能不得不增大堆空間的大小,雖然可以使用的空閑空間是足夠的,但是堆中沒有沒有連續的空間放得下新對象。可能會導緻虛拟機産生不必要的”記憶體不足“錯誤。

(2)使用垃圾收集堆,有一個潛在的缺陷就是加大程式的負擔, 可能影響程式的性能 。因為虛拟機需要追蹤哪些對象被正在執行的程式引用,還要動态釋放垃圾對象。

(3)程式可以調用System.gc()建議jvm去收集垃圾, 但是不能為垃圾回收機制指定某個對象是不是垃圾。即便調用了 gc() , 并不會馬上進行垃圾回收 , 甚至不一定會執行垃圾回收 。所有的記憶體配置設定和回收權限都在jvm,不在開發人員手裡。

可以試試:

public class RubbishRelease {
    // 類的finalize方法,可以告訴垃圾回收器應該執行的操作,該方法從Object類繼承而來。
    // 在從堆中永久删除對象之前,垃圾回收器調用該對象的finalize方法。
    public void finalize() {
        System.out.println("the Object is going...");
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            // 下面不斷建立對象,但是這些對象都沒有被引用
            new RubbishRelease();
            new RubbishRelease();
            new RubbishRelease();
            System.gc();
        }
        System.out.println("The program is over!");
    }
}      

運作結果:

Java垃圾收集學習筆記

(4)垃圾收集算法有很多,但任何垃圾收集算法都必須做兩件事情。首先,它必須檢測出垃圾對象 。其次,它必須 回收垃圾對象所使用的堆空間并還給程式 。

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

(6) 引用計數 是垃圾收集的早期政策。在這種方法中,堆中每一個對象都有一個引用計數。一個對象被建立了,并且指向該對象的引用被配置設定給一個變量,這個對象的引用計數被置為1。當任何其他變量被指派為對這個對象的引用時,計數加1。當一個對象的引用超過了生存期或者被設定一個新的值時,對象的引用計數減1。任何引用計數為0的對象可以被當作垃圾收集。當一個對象被垃圾收集的時候,它引用的任何對象計數值減1。這種方法的好處是,引用計數收集器可以很快地執行,交織在程式的運作之中。這個特性對于程式不能被長時間打斷的實時環境很有利。壞處就是,引用計數無法檢測出循環(即兩個或者更多的對象互相引用)。

(7) 跟蹤收集器 追蹤從根節點開始的對象引用圖。給追蹤過程中遇到對象以某種方式打上标記。追蹤結束時,未被标記的對象就是無法觸及的,進而被收集。基本的追蹤算法被稱作“ 标記并清除” ,這個名字指出垃圾收集過程的兩個階段。

(8)Java虛拟機的垃圾收集器可能有對付堆碎塊的政策。标記并清除收集器通常使用的兩種政策是 壓縮 和 拷貝 。這兩種方法都是快速地移動對象來減少堆碎塊。

(9) 壓縮收集器 把活動的對象越過空閑區滑動到堆的一端,在這個過程中,堆的另一端出現一個大的連續空閑區。所有被移動的對象的引用也被更新,指向新的位置。

(10) 拷貝收集器 把所有的活動的對象移動到一個新的區域。在拷貝過程中,被緊挨着布置,這樣可以消除原本它們在舊區域的空隙。即空閑區。一般的拷貝收集器算法被稱為“停止并拷貝”。此方案中,堆被分成兩個區域,任何時候都使用一個區域。對象在同一個區域中配置設定直到被耗盡。此時,程式執行被中止,堆被周遊,周遊時遇到活動的對象被拷貝到另個區域。當停止和拷貝過程結束時,程式恢複執行。依次往複,對于指定大小的堆來說需要兩倍大小的記憶體,由于任何時候都隻使用其中的一半,這就是該方法帶來的代價。

(11) 按代收集 :根據 對象的存活周期 (一次垃圾收集為一個周期)的不同将記憶體劃分為幾塊。一般是把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最适當的收集算法。在新生代中,每次垃圾收集時都發現有大批對象死去,隻有少量存活,那就選用拷貝算法,隻需要付出少量存活對象的拷貝成本就可以完成收集。而老年代中因為對象存活率高、沒有額外空間對它進行配置設定擔保,可以使用“标記并清除”算法。

(12) 終結方法 (finalize),這個在上面第3點也有提到:這個方法是垃圾收集器在釋放對象前必須運作。這個可能存在的終結方法使得任何Java虛拟機的垃圾收集器要完成的工作更加複雜。因為終結方法可能“複活”了某些不再被引用的對象(本身或者其他對象)。

(13) 堆 中的每一個對象都有 三種狀态 之一: 可觸及的 、 可複活的 以及 不可觸及的 。 可觸及狀态 好了解。關于 可複活狀态 :它在從根節點開始的追蹤圖中不可觸及,但是又可能在垃圾收集器執行某些終結方法時觸及。不僅僅是那些聲明了finalize方法的對象,而是所有的對象都要經過可複活狀态。而 不可觸及狀态 标志着不但對象不再被觸及,而且也不可能通過任何終結方法複活。不可觸及的對象不再對程式的執行産生影響,可自由地回收它們占據的記憶體。

(14)對象的強,軟,弱,虛引用。

強引用:如果一個對象具有強引用,垃圾回收器絕不會回收它。當記憶體空間不足,JVM甯願抛出OutOfMemoryError錯誤,使程式異常終止,也不會考随意回收具有強引用的對象來解決記憶體不足的問題。

軟引用:如果一個對象具有軟引用。如果記憶體空間足夠。垃圾回收器不會回收它。如果記憶體不足了,就會回收這些對象的記憶體。隻要垃圾回收器沒有回收它,該對象就可以被程式使用。軟引用可用來實作記憶體敏感的高速緩存。

弱引用:如果一個對象具有弱引用。當垃圾回收器發現隻具有弱引用對象,不管目前記憶體空間足夠與否,都會回收它的記憶體。不過,由于垃圾回收器是一個優先級很低的線程,是以不一定會很快發現隻具有弱引用的對象。

虛引用:虛引用不會決定對象的生命周期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。

熬夜不易,點選請老王喝杯烈酒!!!!!!!