一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java中的GC收集器詳情

java中的GC收集器詳情

2022-02-25 00:44onlythinking Java教程

這篇文章主要介紹了java中的GC收集器,GC(Garbage collection )指的是程序內存管理分手動和自動,手動內存管理,需要我們編程的時候顯式分配和釋放空間,但如果忘記釋放,會造成嚴重的內存泄漏問題,下面文章內容我們就來實例

1、GC(Garbage collection )

程序內存管理分手動和自動。

手動內存管理,需要我們編程的時候顯式分配和釋放空間,但如果忘記釋放,會造成嚴重的內存泄漏問題。如下:

//申請40MB內存
int* p = malloc(1024 * 1024 * 10 * sizeof(int));
//釋放內存
free(p);


顯式分配和釋放很容易就造成內存泄漏。因此我們希望有一種能自動回收內存的方法,這樣就可以消除人為造成的錯誤。我們將這種自動化稱為垃圾收集(簡稱GC)

現代高級編程語言基本上都具備GC功能。

 

2、GC算法

GC算法按照下面兩方面內容設計

  • 標記出所有活動對象(程序正在使用或者叫可達對象);
  • 刪除未使用的對象和重新整理空間。

2.1標記活動對象

java gc 通過追蹤活動對象進行標記,未被標記的對象為空閑狀態。空閑狀態對象將會在清理階段被回收。

GC標記對象是從GcRoots開始,它是一類特殊對象,分以下幾種:

  • 當前執行方法中的局部變量和方法參數。
  • 活動Java線程。
  • 靜態變量由其類引用。不過類本身是可以被垃圾收集,回收時將刪除所有引用的靜態變量。
  • JNI引用是本機代碼作為JNI調用的一部分創建的Java對象。這樣創建的對象將被特別對待,因為JVM不知道本機代碼是否正在引用它。

標記開始時,GC會遍歷內存中的整個對象樹,從那些GC Roots開始,然后是從根到其他對象(例如實例字段)的引用。GC訪問的每個對象都 標記 為活動對象。

標記結束后,如下圖所示,藍色表示為GCroots仍然在引用的對象,灰色表示為空閑對象等待回收。

標記階段需要注意兩方面:

  • 標記需要暫停應用程序線程,這很好理解如果應用線程一直在運行對象活動狀態就會一直變化,GC就無法進行標記。這種情況稱為 安全點, 導致 Stop The World暫停簡述為(STW)。
  • 暫停的持續時間受活動對象的數量影響,不取決于堆的大小和對象總數 。 因此,增加堆大小不會直接影響標記階段的持續時間。

java中的GC收集器詳情

2.2 刪除空閑對象

GC刪除空閑對象的一般分為三類:

  • 清除,
  • 壓縮,
  • 復制。

2.3 標記清除(Mark-Sweep)

經歷標記階段后,所有空閑對象占用的空間都可以重新分配新對象了。它會維護一個空閑列表,里面記錄的空閑區域的位置和大小。這種方式的缺點很明顯一是維護空閑列表增加對象開銷,二是空閑區域大小不均勻,可能會遇到分配大對象區域不夠存儲的情況。

java中的GC收集器詳情

2.4 清除壓縮(Mark-Sweep-Compact)

清除壓多了一步復制動作彌補標記清除的缺點。它將所有活動對象移動到內存區域的開頭。不過該方式的缺點是增加復制動作,也就增加了GC暫停時間。

java中的GC收集器詳情

2.5 標記和復制

標記復制這種方式與上面標記清除壓縮相似,區別在于它是將活動對象復制到另外一塊新的區域(幸存對象區域)。它的好處在于復制動作可以與標記階段同時進行,缺點是需要另外一個存儲區域,該存儲區域應足夠大以容納幸存的對象。

java中的GC收集器詳情

 

3、JVM GC

在較舊的JVM GC中(串行,并行,CMS)將堆分成三個部分:固定內存大小的年輕代,年老代和永久代。

JVM使用兩種GC算法分別對年輕代和年老代對象進行回收。年輕代的進行標記復制操作,年老代回收進行標記清除壓縮。

java中的GC收集器詳情

3.1 JVM GC事件

我們把GC清除堆不同區域的觸發事件分為以下幾種:

  • Minor GC 從年輕代空間回收稱為次要GC。
  • Major GC 從年老代空間回收主要GC。
  • Full GC 清理整個堆空間,包括年輕代和年老代。

3.2 Serial GC

串行GC,年輕代進行標記復制,年老代進行標記清除壓縮。兩個GC都是單線程操作,并且觸發STW,停止所有應用線程。多CPU計算機中基本不會使用這個GC收集器。只有在單CPU的服務器上使用才有意義。

java -XX:+UseSerialGC

3.3 Parallel GC

并行GC,年輕代進行標記復制,年老代進行標記清除壓縮。不管是年輕代還是年老代GC時都會觸發STW,停止所有應用線程。與串行GC的區別在于它是使用多個線程運行標記和復制/壓縮,多線程可以縮短GC收集時間。

java8默認GC收集器就是 parallel gc。不過因為它在標記清理階段仍然需要停止應用線程,所以在要求較低延遲的場景下可能變得不那么適用。

可以通過-XX:ParallelGCThreads = NNN指定處理的線程數量 。默認值等于計算機中的內核數。

java -XX:+UseParallelGC #使用并行垃圾收集進行清理
java -XX:+UseParallelOldGC #將并行垃圾回收用于。啟用此選項會自動設置-XX:+ UseParallelGC
java -XX:+UseParallelGC -XX:+UseParallelOldGC

3.4 Concurrent Mark and Sweep

并發標記掃描(CMS),年輕代空間執行并行標記復制,年老代空間執行并發標記清除。年輕代GC時觸STW,停止所有應用線程,然后多線程并行收集。年老代并發標記清除不需要暫停應用線程。它的意義在于著避免了Parallel GC收集器在年老代GC時的長時間停頓。

默認情況下,此GC方式使用的線程數等于計算機物理內核數的1/4。

java -XX:+UseConcMarkSweepGC

我們看下CMS經歷的幾個階段

(1)初始標記,暫停應用線程,標記年老代中的所有對象,這些對象是GC Roots,和年輕代中的某些活動對象引用的。

java中的GC收集器詳情

(2)并發標記,GC與應用程序線程并行運行,從初始標記中的根對象開始,遍歷年老代所有活動對象進行標記。

java中的GC收集器詳情

(2)并行預清除,與應用線程同時運行,如果某些引用發生了變更,JVM會將變化的區域標記為臟區域。預清除階段就是對這些臟區域進行處理,并標記還在存活的對象,然后空閑對象將被清除。預清除可以減少重標階段的工作量。

java中的GC收集器詳情

(4)并發可中止預清除,該階段也與應用線程并行,屬于優化。增加這個階段是為了讓我們能控制該階段結束的時間,也是為了減輕重標階段的工作量。

# 控制參數
-XX:CMSScheduleRemarkEdenSizeThreshold=2M
-XX:CMSScheduleRemarkEdenPenetration=50
-XX:CMSMaxAbortablePrecleanTime=5000(單位為毫秒)


比如在并發預清理之后,如果年輕代占用高于CMSScheduleRemarkEdenSizeThreshold,則開始并發可中止的預清除并繼續進行預清除,直到年輕代中達到CMSScheduleRemarkEdenPenetration百分比占用率,之后進入重標階段。如果經過CMSMaxAbortablePrecleanTime時間仍然未達到要求,則直接進入重標階段。

(5)重標階段,觸發STW,暫停所用應用線程。從GCroots 開始掃描標記年老代的所有活動對象。CMS會嘗試在年輕代盡可能空的時候運行最后的備注階段。

(6)并行清理,應用線程同時執行。該階段的目的是刪除未使用的對象,并回收它們占用的空間以備將來使用。

(7)并行復位,并發執行階段,重置CMS算法的內部數據結構,并為下一個周期做好準備。

:如上CMS垃圾收集器進行大量工作為的是在年老代回收時不需要暫停應用線程,以減少暫停時間。但是,它存在一些缺點,其中最明顯的是年老代碎片,并且在某些情況下,尤其是在大堆上,暫停持續時間缺乏可預測性。

3.5 G1 C垃圾優先

G1是Java9默認GC收集器。它設計的目標是應用在大內存的多處理器計算機,實現高吞吐量。一般應用堆應該在6GB以上且可預測的暫停時間低于0.5秒。G1作為并發標記掃描收集器(CMS)的替代產品。

G1堆內存與舊GC收集器堆內存管理完全不同。它將堆拆分為多個較小的區域(默認根據堆內存拆分為接近2048份)來存對象。

java中的GC收集器詳情

G1收集器的幾個階段:

(1)初始標記,觸發STW,標記出從GC Roots直接訪問的所有活動對象。

java中的GC收集器詳情

(2)并發標記,從已標記的對象開始掃描,并從根開始標記所有可訪問的對象。這個階段可以被年輕一代的垃圾收集打斷。

java中的GC收集器詳情

(3)重新標記,因為并發標記與應用線程并行,所以可能存在遺漏的更新對象。此階段觸發STW,應用線程暫停,完成活動對象最后的標記。

java中的GC收集器詳情

(4)復制/清理階段,G1選擇“活度”最低的區域,這些區域可以被最快地收集。并發標記完成后將進行[GC pause (mixed)]混合GC,年輕代和年老代同時收集。

java中的GC收集器詳情

下圖深綠色和深藍色為清除壓縮之后的區域。

java中的GC收集器詳情

G1中幾個重要的參數:

# G1區域的大小。該值為2的冪,范圍為1MB至32MB。目標是根據最小Java堆大小具有大約2048個區域。
-XX:G1HeapRegionSize=n

# 所需的最大暫停時間設置目標值。默認值為200毫秒。
-XX:MaxGCPauseMillis=200

# 設置要用作年輕代大小的最小值的堆百分比。默認值為Java堆的5%
-XX:G1NewSizePercent=5

# 設置堆大小的百分比,以用作年輕代大小的最大值。默認值為Java堆的60%。
-XX:G1MaxNewSizePercent=60

# 設置STW工作線程的值。將n的值設置為邏輯處理器的數量。的值與n邏輯處理器的數量相同,最多為8
# 如果邏輯處理器多于八個,則將的值設置為邏輯處理器的n大約5/8。在大多數情況下,這n是可行的,但大型SPARC系統的值可能約為邏輯處理器的5/16。
-XX:ParallelGCThreads=n

# 設置平行標記線的數量。設置n為并行垃圾回收線程數(ParallelGCThreads)的大約1/4 。
-XX:ConcGCThreads=n

# 設置觸發標記周期的Java堆占用閾值。默認占用率為整個Java堆的45%。
-XX:InitiatingHeapOccupancyPercent=45

# 設置要包含在混合垃圾收集周期中的舊區域的占用閾值。默認占用率為65%。
-XX:G1MixedGCLiveThresholdPercent=65

# 當可回收百分比小于堆垃圾百分比時,Java HotSpot VM不會啟動混合垃圾回收周期。默認值為10%。
-XX:G1HeapWastePercent=10

# 設置標記周期后混合垃圾回收的目標數量,以收集最多包含G1MixedGCLIveThresholdPercent實時數據的舊區域。默認值為8個混合垃圾回收。混合館藏的目標是在此目標數量之內。
-XX:G1MixedGCCountTarget=8

# 設置在混合垃圾收集周期中要收集的舊區域數的上限。缺省值為Java堆的10%。
-XX:G1OldCSetRegionThresholdPercent=10

# 設置保留內存的百分比以使其保持空閑狀態,以減少空間溢出的風險。默認值為10%。當增加或減少百分比時,請確保將總Java堆調整相同的數量。
-XX:G1ReservePercent=10

 

4、總結

本文記錄GC算法基礎和Java中的幾種GC收集器。

到此這篇關于java中的GC收集器詳情的文章就介紹到這了,更多相關java中的GC收集器內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.onlythinking.com/2020/12/08/java-g1%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 人与蛇boxxⅹ | 免费一级黄 | 性绞姿始动作动态图 | 激情视频亚洲 | 4hu影院永久在线播放 | 国产一区二区三区高清 | 色吧导航| 欧美怡红院视频一区二区三区 | 国产精品成人亚洲 | 岛国最新资源网站 | 全黄一级裸片视频免费 | 欧美日韩国产精品自在自线 | 成人在线视频播放 | 男人天堂网在线 | 亚洲AV国产精品无码精 | 青青在线观看 | 丝袜美女被艹 | 国产在视频线在精品 | 久久香蕉国产免费天天 | free白嫩性hd | 色猪视频 | 亚洲欧美日韩综合在线 | 国四虎影永久 | 天美传媒果冻传媒星空传媒 | 欧美a在线观看 | 欧美ay| 日韩精品一区二区三区免费视频 | 91污无限制破解安卓2021 | 高清国语自产拍免费视频国产 | 免费看一级a一片毛片 | 午夜小福利 | 国产午夜精品一区二区 | 色琪琪久久草在线视频 | 九九免费高清在线观看视频 | 99热在线免费观看 | 玩50岁四川熟女大白屁股直播 | 亚洲小视频 | 和老外3p爽粗大免费视频 | 精品无码久久久久久久动漫 | 激情三级hd中文字幕 | 国产精品久久久久久久久久久搜索 |