文章目錄
- 前言
- 一、什么算是垃圾?
- 二、怎么判斷垃圾是否是垃圾?(如何定位)
- 1.參考計數法
- 2.根可達演算法
- 三、垃圾回收演算法
- 1.標記-清除演算法(Mark-Sweep)
- 2.復制演算法(Copying)
- 3.標記-壓縮演算法(Mark-Compact)
- 四、堆記憶體邏輯磁區
- 1. 新生代
- 2. 老年代
- 3. 設定引數
- 總結
前言
上一次談到JVM虛擬機中記憶體是如何劃分的,以及什么情況下會造成這些區域發生記憶體溢位的例外,學習Java的大伙都知道,Java為避免記憶體溢位的情況發生,有良好的垃圾自動回識訓制,那本章就來談一談Java的垃圾回收,
一、什么算是垃圾?
沒有任何參考指向的一個物件稱之為一個垃圾,
沒有任何參考指向的多個物件(回圈參考)稱為一堆垃圾,
二、怎么判斷垃圾是否是垃圾?(如何定位)
1.參考計數法
給物件添加一個參考計數器,當有一個地方參考他時,參考計數器加1;當參考失效時,參考計數器減1,當在任何時刻,參考計數器的值為0的
物件就是不可能再被使用的物件,
缺陷:這種方式定位不到回圈參考的情況,也就是物件之間相互參考,
2.根可達演算法
從GC Root的物件作為起點,一直向下搜索,所走過的路徑稱為參考鏈,
當一個物件到GC Root沒有任何一條參考鏈相連時,則證明這個物件是
不可用的,

在Java中,GC Root有以下幾種,
- 虛擬機堆疊(堆疊幀中的本地變數表)中參考的物件,
- 方法區中類靜態屬性參考的物件,(靜態變數)
- 方法區中常量參考的物件,(常量池)
- 本地方法堆疊中JNI(即一般說的Native方法)參考的物件,
三、垃圾回收演算法
1.標記-清除演算法(Mark-Sweep)
- 首先“標記”出所有需要回收的物件,
- 隨后對標記的物件進行清除,
缺陷:第一個缺陷是性能問題,標記和清除這兩個程序的效率都不高,其次是這樣標記-清除之后,會產生大量不連續的空間碎片,太多的空間碎片,會導致在需要為一個大的物件分配一片空間是,因為記憶體空間不足,提前觸發下一次GC,如下圖,

2.復制演算法(Copying)
將記憶體分為大小相等的兩個區域(A和B),每次只使用一個區域,如A區域的空間用完了,就將A區域中所有還存活的物件全部復制到B區域中,然后整體清除A區域,這樣的做法很高效,
缺陷:將記憶體直接砍為一半,太狠了,浪費空間,如下圖,

3.標記-壓縮演算法(Mark-Compact)
標記程序與標記-清除演算法一致,但是在后續清除操作時,沒有直接操作,而是將所有存活的物件全部移向一端,然后直接清理掉端邊界意外的記憶體,沒有碎片產生,
缺陷:程序效率偏低,如下圖,

四、堆記憶體邏輯磁區
從分代GC的角度看,堆分為新生代和老年代
1. 新生代
- 新生代分為Eden + 2個survivor區
- 當無法在新生代為物件分配空間時,會產生YGC,YGC使用的演算法
是上邊提到的復制演算法(Copying),復制演算法需要額外的空間,所
以除了Eden區,還有survivor區,一般Eden和survivor的空間比例
8:1:1,
垃圾回收流程
*s0是第一個survivor區,s1是第二個survivor區,
- 第一次YGC:大多數物件都會被回收,Eden -> s0
- 第二次YGC:Eden + s0 -> s1
- 第三次YGC:Eden + s1 -> s0
- 當物件在新生代年齡(被復制的次數)足夠大,則進入老年代,
追加一些知識,
- 用 -XX:MaxTenuringThreshold可以設定年齡閾值,
- Parallel Scavenge垃圾回收器進入老年代年齡默認為15、CMS回收器為6、G1回收器為15,
- 動態年齡判定:Hotspot遍歷所有物件時,按照年齡從小到大對其所占用的大小進行累積,當累積的某個年齡大小超過了survivor區的一半時,取這個年齡和MaxTenuringThreshold中更小的一個值,作為新的晉升年齡閾值
- 記憶體分配擔保:YGC時,JVM會首先檢查老年代最大的可用連續空間,是否大于新生代所有物件的總和,如果大于,那么這次YGC是安全的,如果不大于的話,JVM就需要判HandlePromotionFailure是否允許空間分配擔保,
1.允許空間分配擔保:JVM繼續檢查老年代最大的可用連續空間是否大于歷次晉升到老年代的所有物件總的平均大小,如果大于表示此處YGC相對安全,正常進行一次YGC,如果小于,進行FGC,
2.不允許空間分配擔保:FGC
2. 老年代
- 進入老年代的物件,除非要垃圾回收,不然它會終身存在,
- 在老年代區域會產生FGC(Full GC),使整個記憶體都會回收,效率比較低,會產生STW(Stop-The-World),所有執行緒暫停,進行垃圾回收,
- 老年代中因為物件存活率高、沒有額外空間 對它進行分配擔保,就必須使用“標記—清除”或者“標記—壓縮”演算法來進行回收,
在GC調優中,很重要的一個目的就是為了減少FGC,
3. 設定引數
- -Xmn 指定新生代記憶體大小
- -Xms:指定堆記憶體最小值
- -Xmx:指定堆記憶體最大值
總結
本章了解了垃圾回收的一些基本知識,認識了三種垃圾回收演算法,下一篇文章重點總結10種垃圾回收器的知識,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/246544.html
標籤:java
上一篇:2021108作業
