好程式設計師Java培訓分享Java教程垃圾回收與演算法

好程式設計師發表於2020-07-14

   好程式設計師Java 培訓分享 Java 教程垃圾回收與演算法 首先來講一下 如何確定垃圾

   引用計數法:在Java 中,引用和物件是有關聯的。如果要操作物件則必須用引用進行。因此,很顯然一個簡單的辦法是透過引用計數來判斷一個物件是否可以回收。簡單說,即一個物件如果沒有任何與之關聯的引用,即他們的引用計數都不為 0 ,則說明物件不太可能再被用到,那麼這個物件就是可回收物件。

   可達性分析:為了解決引用計數法的迴圈引用問題,Java 使用了可達性分析的方法。透過一系列“ GC roots ”物件作為起點搜尋。如果在“ GC roots ”和一個物件之間沒有可達路徑,則稱該物件是不可達的。要注意的是,不可達物件不等價於可回收物件,不可達物件變為可回收物件至少要經過兩次標記過程。兩次標記後仍然是可回收物件,則將面臨回收。

   垃圾回收演算法

   標記清除演算法(Mark-Sweep) 最基礎的垃圾回收演算法,分為兩個階段,標註和清除。標記階段標記出所有需要回收的物件,清除階段回收被標記的物件所佔用的空間。該演算法最大的問題是記憶體碎片化嚴重,後續可能發生大物件不能找到可利用空間的問題。

   複製演算法(copying) 為了解決 Mark-Sweep 演算法記憶體碎片化的缺陷而被提出的演算法。按記憶體容量將記憶體劃分為等大小的兩塊。每次只使用其中一塊,當這一塊記憶體滿後將尚存活的物件複製到另一塊上去,把已使用的記憶體清掉。這種演算法雖然實現簡單,記憶體效率高,不易產生碎片,但是最大的問題是可用記憶體被壓縮到了原本的一半。且存活物件增多的話, Copying 演算法的效率會大大降低。

   分代收集演算法分代收集法是目前大部分JVM 所採用的方法,其核心思想是根據物件存活的不同生命週期將記憶體劃分為不同的域,一般情況下將 GC 堆劃分為老生代 (Tenured/Old Generation) 和新生代 (Young Generation) 。老生代的特點是每次垃圾回收時只有少量物件需要被回收,新生代的特點是每次垃圾回收時都有大量垃圾需要被回收,因此可以根據不同區域選擇不同的演算法。

   新生代與複製演算法

   目前大部分JVM GC 對於新生代都採取 Copying 演算法,因為新生代中每次垃圾回收都要回收大部分物件,即要複製的操作比較少,但通常並不是按照 1 1 來劃分新生代。一般將新生代劃分為一塊較大的 Eden 空間和兩個較小的 Survivor 空間 (From Space, To Space) ,每次使用 Eden 空間和其中的一塊 Survivor 空間,當進行回收時,將該兩塊空間中還存活的物件複製到另一塊 Survivor 空間中。

   老年代與標記複製演算法

   老年代因為每次只回收少量物件,因而採用Mark-Compact 演算法。

   (1)Java 虛擬機器提到過的處於方法區的永生代 (Permanet Generation) ,它用來儲存 class 類,常量,方法描述等。對永生代的回收主要包括廢棄常量和無用的類。

   (2) 物件的記憶體分配主要在新生代的 Eden Space Survivor Space From Space(Survivor 目前存放物件的那一塊 ) ,少數情況會直接分配到老生代。

   (3) 當新生代的 Eden Space From Space 空間不足時就會發生一次 GC ,進行 GC 後, Eden Space From Space 區的存活物件會被挪到 To Space ,然後將 Eden Space From Space 進行清理。

   (4) 如果 To Space 無法足夠儲存某個物件,則將這個物件儲存到老生代。

   (5) 在進行 GC 後,使用的便是 Eden Space To Space 了,如此反覆迴圈。

   (6) 當物件在 Survivor 區躲過一次 GC 後,其年齡就會 +1 。預設情況下年齡到達 15 的物件會被移到老生代中。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913864/viewspace-2704364/,如需轉載,請註明出處,否則將追究法律責任。

相關文章