1. 程式人生 > 其它 >java學習筆記 2021.10.24

java學習筆記 2021.10.24

2021.10.24

JVM

垃圾回收概述

概述

垃圾回收不只是java的特有,其他的也有體現,但現在已經成了java的招牌能力,極大的提高了開發的效率。

可以說,現在自動化的記憶體分配和垃圾回收的方式已經成為現代開發語言必備的標準。

關於垃圾回收的三個基本問題

垃圾是什麼:

是指在執行程式中沒有任何指標指向的物件

當然,這是針對程式中的引用變數而言的,基本資料型別就不存在這樣的問題。

為什麼需要垃圾回收器

反正基本的一個理念就是合理運用空間。

JAVA垃圾回收機制

當然這也會導致一些缺點,即會弱化JAVA開發人員在程式出現記憶體溢位時定位問題和解決問題的能力。

所以說,瞭解記憶體分配和垃圾回收的機制還是很重要的,有利於後面解決問題。

GC的作用區域

這裡跟前面講執行時資料區是對應好的。

垃圾回收相關演算法

重在使用和場景的理解,而不是在演算法的實現上。

垃圾標記階段

引用計數演算法

垃圾標記的意義即在於判斷哪些物件需要被回收。當然這句話的前提也是建立在認為垃圾回收的主要部分還是在堆中,針對具體物件的。而不是針對GC很少的方法區。

引用計數法:

  • 第二部分即是引用計數法操作的原理。

上圖即體現了迴圈引用的缺點所在,可以看到當p的引用失效的時候,物件的具體的引用計數器的值沒有為,即沒法被回收,自然也就導致了記憶體洩漏。

視訊中有對java不是使用引用計數演算法的驗證例項。有興趣可以去看,反正意思就是java能夠處理迴圈引用使得計數器不為0的物件。

小結:

可達性分析演算法

大概就是下面這種情況:

基本的實現原理

因此,這裡可以看出,對於GC roots的重要性,至少需要知道GC roots包括哪些型別,才能去了解到他後面能夠怎麼展開。

下圖就是GC roots包括的各種元素:

這裡提供一個判斷roots的小技巧,所以對於一個指標,當它儲存了堆記憶體裡面的物件,但是自己又不存放在堆記憶體裡,那他就是一個root。

一些特殊情況:

區域性回收意思就是以伊甸區為目標回收的話,老年區之類的也可以作為roots。

一些注意點:

物件的finalization機制

簡單理解就是垃圾回收之前處理好後事,把相關的一些東西都關閉了。並且也只有在垃圾回收時才會呼叫這個方法。

注意點:

三種可能的狀態,即是對於垃圾回收標記階段非常重要的一個理解:

  • 注意這裡finalization只能被呼叫一次的意思就是就算被複活成功了,在第二次引用都被釋放完之後,也是無法再呼叫finalization方法了。

具體的實現過程:

  • 這裡二也對應了沒法主動呼叫方法的情況,會自動建立執行緒來對其進行呼叫。
  • 第一次標記是沒有引用鏈的時候,第二次標記是呼叫該方法的時候。
  • 該方法主要用於在物件被回收的時候進行資源釋放,通過視訊裡有的演示也可以看出前面執行的整個邏輯,有興趣可以參考視訊例項。
  • 同時也想說下程式碼中this、super之類的應該也是堆中的物件。

GC Roots溯源

通常的使用場景即是判斷具體物件的roots溯源,從而使在oom情況下看有沒有出現記憶體洩露的情況。常用的工具有mat和jprofiler。後面有用到的時候再去具體瞭解。同樣jprofiler還可以分析oom,在後面的調優的學習中也都會涉及到。

垃圾清除階段

標記-清除演算法

具體的實現過程:

  • 標記的意義即在於避免在垃圾回收的過程中又出現了新的垃圾。
  • 注意標記的是可達物件,即非垃圾物件。
  • 優點即是比較基礎和常見
  • 效率不算高在兩次的遍歷過程中也能夠體會到。
  • 空閒記憶體的理解也在清楚的垃圾的位置的情況能夠理解。並且空閒列表本身也要消耗記憶體。
  • 注意清除的做法也是如上圖所示,沒有真正的刪除,通過放新的覆蓋來刪除。
複製演算法

核心思想:

圖示:

  • 也是要對可達物件進行遍歷,然後不用標記,直接複製到另外一個區域。
  • 之後即是對兩個區域的反覆操作。
  • 即是前面有提到過的新生區的s0區和s1區的工作機制。

具體的優缺點:

注意就是對比著前面的標記清楚演算法。

  • 缺點的第二點其實也就說明物件的位置發生了變化,會導致區域性變量表中的引用位置也要發生變化。
  • 最後一點即是說一下最好活著的物件並不是太多的情況。
  • 更是直接對應了s區的演算法的選擇。
標記-壓縮演算法

考慮到前面所說的複製演算法,不適合用在老年區中,並且老年區中對記憶體碎片也很敏感,所以也不考慮標記清除演算法。所以才考慮引入了這種演算法。

執行過程:

也叫標記整理演算法,反正就是把活著的整理一下排下序。讓記憶體不再碎片化。

當然從上面也可以看出也存在引用指標轉移的問題。

具體的優缺點:

三種演算法的總結

綜合來看,還是標記壓縮演算法比較理想化的。

分代收集演算法

以具體問題具體分析的角度出發總結出來的演算法

現在幾乎所有的垃圾回收都是基於分代收集演算法來執行的,具體的對應代的演算法選擇如下:

  • 通過s區緩解記憶體的原理即在於s區任意一個所佔堆空間的比例就是很小的,有效避免了複製演算法中說兩個空間帶來的記憶體佔用的問題。

下面就是一個結合演算法的老年區的垃圾回收器的舉例,具體後面再說

增量收集演算法

基礎還是上面的基本演算法,核心就是讓垃圾執行緒和使用者執行緒的交替進行。主要處理的也就是幾個執行緒之間的衝突。

缺點即在於執行緒切換和上下文轉換的消耗,會使得垃圾回收的總體成本上升,造成系統吞吐量的下降。

分割槽演算法

包括常用的g1垃圾回收器也是用的這種,後面學到時再詳細解釋。

垃圾回收相關概念