回覆列表
  • 1 # 教女朋友學程式設計

    垃圾回收 讓程式設計師把精力放在了 業務邏輯上,而不是記憶體管理上!

    缺點是 讓程式設計師更傻了,對底層更加不瞭解!

  • 2 # 瞥瞥張

    引用計數演算法

    給物件新增一個引用計數器,每當一個地方引用它時,資料器加1;當引用失效時,計數器減1;計數器為0的即可被回收。

    優點:實現簡單,判斷效率高缺點:很難解決物件之間的相互迴圈引用(objA.instance = objB; objB.instance = objA)的問題,所以java語言並沒有選用引用計數法管理記憶體根搜尋演算法

    Java和C#都是使用根搜尋演算法來判斷物件是否存活。透過一系列的名為“GC Root”的物件作為起始點,從這些節點開始向下搜尋,搜尋所有走過的路徑稱為引用鏈(Reference Chain),當一個物件到GC Root沒有任何引用鏈相連時(用圖論來說就是GC Root到這個物件不可達時),證明該物件是可以被回收的。

    在Java中這些物件可以成為GC Root:

    虛擬機器棧(棧幀中的本地變量表)中的引用物件

    方法區中的類靜態屬性引用的物件

    方法區中的常量引用物件

    本地方法棧中JNI(即Native方法)的引用物件

    標記-清除演算法

    標記-清除演算法是一種常見的基礎垃圾收集演算法,它將垃圾收集分為兩個階段

    標記階段:標記出可以回收的物件。

    清除階段:回收被標記的物件所佔用的空間。

    標記-清除演算法主要有兩個缺點,一個是標記和清除的效率不高,另一個從圖中就可以看出,就是容易產生大量不連續的記憶體碎片,碎片太多可能會導致後續沒有足夠的連續記憶體分配給較大的物件,從而提前觸發新的一次垃圾收集動作。

    複製演算法

    為了解決標記-清除演算法的效率不高的問題,產生了複製演算法。它把記憶體空間劃分為兩個相等的區域,每次只使用其中一個區域。在垃圾收集時,遍歷當前使用的區域,把存活物件複製到另一個區域中,最後將當前使用的區域的可回收的物件進行回收。

    這種演算法每次都對整個半區進行記憶體回收,不需要考慮記憶體碎片的問題,代價就是使用記憶體為原來的一半。複製演算法的效率與存活物件的數目多少有很大的關係,如果存活物件很少,複製演算法的效率就會很高。由於絕大多數物件的生命週期很短,並且這些生命週期很短的物件都存於新生代中,所以複製演算法被廣泛應用於新生代中。

    標記-壓縮演算法

    在新生代中可以使用複製演算法,但是在老年代就不能選擇複製演算法,因為老年代物件存活率會較高,這樣會有較多的複製操作,導致效率變低。標記-清除演算法可以應用在老年代中,但是效率不高,在記憶體回收後容易產生大量記憶體碎片。因此就出現了一種標記-壓縮演算法,與標記-清除演算法不同的是,在標記可回收的物件後將所有存活的物件壓縮到記憶體的一端,使它們緊湊地排列在一起,然後對邊界以外的記憶體進行回收,回收後,已用和未用的記憶體都各自一邊。

    標記-壓縮演算法解決了標記-清除演算法效率低和容易產生大量記憶體碎片的問題,它被廣泛應用於老年代中。

    分代收集演算法

    分代收集演算法會結合不同的收集演算法來處理不同的空間,因此在學習分代收集演算法之前我們首先要了解Java堆區的空間劃分。Java堆區的空間劃分在Java虛擬機器中,各種物件的生命週期會有著較大的差別,大部分物件生命週期很短暫,少部分物件生命週期很長,有的甚至與應用程式以及Java虛擬機器的執行週期一樣長。因此,應該對不同生命週期的物件採取不同的收集策略,根據生命週期長短將它們放到不同的區域,並在不同的區域採用不同的收集演算法,這就是分代的概念。現在主流的Java虛擬機器的垃圾收集器都採用分代收集演算法。Java堆區基於分代的概念,分為新生代和老年代,其中新生代再細分為Eden空間、From Survivor空間和To Survivor空間。因為Eden空間中的大多數生命週期很短,所以新生代的空間劃分並不是均分的,HotSpot虛擬機器預設Eden空間和兩個Survivor空間的所佔的比例為8:1。

    根據Java堆區的空間劃分,垃圾收集的型別分為兩種,它們分別如下:

    Minor Collection:新生代垃圾收集。

    Full Collection:對老年代進行收集,又可以稱作Major Collection,Full Collection通常情況下會伴隨至少一次的Minor Collection,它的收集頻率較低,耗時較長。

    當執行一次Minor Collection時,Eden空間的存活物件會被複制到To Survivor空間,並且之前經過一次Minor Collection 並在From Survivor空間存活的仍年輕的物件也會複製到To Survivor空間。有兩種情況Eden空間和From Survivor空間存活的物件不會複製到To Survivor空間, 而是晉升到老年代。一種是存活的物件的分代年齡超過-XX:MaxTenuringThreshold(用於控制物件經歷多少次Minor GC 才晉升到老年代)所指定的閾值。另一種是To Survivor空間容量達到閾值。當所有存活的物件被複制到To Survivor空間,或者晉升到老年代,也就意味著Eden空間和From Survivor空間剩下的都是可回收物件。

    這個時候GC執行Minor Collection,Eden空間和From Survivor空間都會被清空,新生代存活的物件都存放在To Survivor空間。接下來將From Survivor空間和To Survivor空間互換位置,也就是此前的From Survivor空間成為了現在的To Survivor空間,每次Survivor空間互換都要保證To Survivor空間是空的,這就是複製演算法在新生代中的應用。在老年代則會採用標記-壓縮演算法或標記-清除演算法。

  • 中秋節和大豐收的關聯?
  • 《我不是購物狂》高楊找工作要求太高,你求職時是什麼樣呢?