java g1 gc ref proc_深入理解垃圾收集器的G1及日志分析

盡管Hotspot 最新的垃圾回收器G1是在2006年推出的。但是G1從推行至今的市場反響來看,但現在足以證明這款垃圾收集器是經得起考驗的,從java9開始,就默認為G1垃圾收集器。G1是一款面向服務端應用的垃圾收集器。HotSpot開發團隊賦予它的使命是(在比較長期的)未來可以替換掉JDK1.5中發布的CMS收集器。與其他GC收集器相比,G1具備如下特點。

并行與并發、分代收集的垃圾收集算法、可預測的停頓、空間整合。

特點

從分代來看,G1依然屬于分代垃圾收集器,她會區分年輕代和老年代,依然有eden區和survivor區,但從堆的結構來看,它并不要求整個eden、年輕代或者老年代都連續,它使用了分區算法。

并行性: 在回收期間,可以由多個GC線程同時工作,有效利用多核計算能力。

井發性: GI 擁有與應用程序交替執行的能力,部分工作可以和應用程序同時執行,因此一 般來說,不會在整個回收期間完全阻塞應用程序。

分代 GC : Gl 依然是一個分代收集器,但是和之前回收器不同,它同時兼顧年輕代和老年代。對比其他回收器,它們或者工作在年輕代,或者工作在老年代。因此,這里是一個很大的不同。

空間整理: Gl 在回收過程中,會進行適當的對象移動,不像CMS,只是簡單地標記清理對象,在若干次 GC 后,CMS 必須進行一次碎片整理。而Gl不同,它每次回收都會有效地復制對象,減少空間碎片。

G1把內存“化整為零”的思路,理解起來似乎很容易,但其中的實現細節卻遠遠沒有想象中那樣簡單,否則也不會從2004年Sun實驗室發表第一篇G1的論文開始直到今天(將近10年時間)才開發出G1的商用版。

筆者以一個細節為例:把Java堆分為多個Region后,垃圾收集是否就真的能以Region為單位進行了?聽起來順理成章,再仔細想想就很容易發現問題所在:Region不可能是孤立的。一個對象分配在某個Region中,它并非只能被本Region中的其他對象引用,而是可以與整個Java堆任意的對象發生引用關系。那在做可達性判定確定對象是否存活的時候,豈不是還得掃描整個Java堆才能保證準確性?這個問題其實并非在G1中才有,只是在G1中更加突出而已。在以前的分代收集中,新生代的規模一般都比老年代要小許多,新生代的收集也比老年代要頻繁許多,那回收新生代中的對象時也面臨相同的問題,如果回收新生代時也不得不同時掃描老年代的話,那么Minor GC的效率可能下降不少。

?在G1收集器中,Region之間的對象引用以及其他收集器中的新生代與老年代之間的對象引用,虛擬機都是使用Remembered Set來避免全堆掃描的。G1中每個Region都有一個與之對應的Remembered Set,虛擬機發現程序在對Reference類型的數據進行寫操作時,會產生一個Write Barrier暫時中斷寫操作,檢查Reference引用的對象是否處于不同的Region之中(在分代的例子中就是檢查是否老年代中的對象引用了新生代中的對象),如果是,便通過CardTable把相關引用信息記錄到被引用對象所屬的Region的RememberedSet之中。當進行內存回收時,在GC根節點的枚舉范圍中加入Remembered Set即可保證不對全堆掃描也不會有遺漏。

G1的內存劃分和主要收集過程

G1收集器講堆進行分區,劃分為一個個區域,每次收集時,只收集其中幾個區域,以此來控制垃圾回收產生的一次停頓時間。

G1收集過程四個階段:

新生代GC(YGC)

并發標記周期

混合收集

如果需要進行full GC

G1的新生代GC

新生代GC的主要工作是回收eden區和survivor區。 一旦eden 區被占滿,新生代GC就會啟動。新生代GC收集前后的堆數據如圖5.6所示,其中E表示eden區,S表示survivor區, o表示老年代。可以看到,新生代GC只處理eden和survivor區,回收后,所有的eden區都應該被消空,而survivor區會被收集一 部分數據,但是應該至少仍然存在一 個 survivor 區,類比其他的新生代收集器,這一 點似乎并沒有太大變化。另一 個亟要的變化是老年代的區域增多,因為部分survivor區或者eden區的對象可能會晉升到老年代。

f6be2cfc74e940932c8f492a257a9660.png

c38ade774b58619a366cb335edf4d15c.png

從日志中可以看到,eden區原本占用235MB空間,回收后被清空,survivor區從5MB增長到了11MB, 這是因為部分對象從eden區復制到survivor區,整個堆合計為400MB, 從回收前的239MB下降到10.5MB。

G1的井發標記周期

G1的并發階段與CMS有點類似,他們都是為了降低一次停頓時間,而將可以和應用程序并發的部分單獨提取出來執行。

并發標記周期可以分為以下幾步。如果不計算維護RememberedSet的操作,G1收集器的運作大致可劃分為以下幾個步驟:

初始標記(Initial Marking)

根區域掃描

并發標記(Concurrent Marking)

最終標記(Final Marking)

獨占清理

篩選回收(Live Data Counting and Evacuation)

復制代碼

初始標記: 標記從根節點直接可達的對象。這個階段會伴隨一次新生代GC,它會產生全局停頓。

根區域掃描: 由于初始標記必然會伴隨一次新生代的GC,所以在初始化標記后,eden被清空,并且存活對象被移入survivor區。這個階段,將掃面survivor區直接可達的老年代對象,并標記這些直接可達的對象。根區域掃描不能和新生代GC同時執行。

并發標記: 和CMS類似,掃面查找整個對存活的對象,這是一個并發的過程,可以被一次新生代GC打斷。

重新標記: 由于并發標記過程中,應用仍在執行,因此標記結果需要修正,所以對上一次的標記結果進行補充,在G1中,這個過程使用STAB算法完成。即G1會在標記之初為存活對象創建一個快照,有助于加速重新標記速度。

獨占清理: 這個階段會引起停頓。

并發清理階段: 識別并清理完全空閑的區域。它是并發的清理,不會引起停頓。

3505cc04e4ec74e9bcc2fb43ff3bcd3e.png

9e73e8c90fff874ffd1a07961cccb453.png

在并發標記周期時,G1會產生如下日志:

(1)、初始標記,伴隨一次新生代GC

[GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0117414 secs]

...

[Eden: 1024.0K(4096.0K)->0.0B(2048.0K) Survivors: 2048.0K->1024.0K Heap: 9581.8K(20.0M)->12.3M(20.0M)]

[Times: user=0.11 sys=0.00, real=0.01 secs]

復制代碼

可以看到初始化標記時,eden被清空,并部分復制到survivor區

(2)、這是一次并發的根區域掃描,并發掃面過程中,不能被新生代GC打斷。

[GC concurrent-root-region-scan-start]

[GC concurrent-root-region-scan-end, 0.0007368 secs]

復制代碼

(3)、下面這個是指并發標記

[GC concurrent-mark-start]

[GC pause (G1 Evacuation Pause) (young) (to-space exhausted), 0.0427113 secs]

.....

[Eden: 2048.0K(2048.0K)->0.0B(1024.0K) Survivors: 1024.0K->1024.0K Heap: 16.4M(20.0M)->18.0M(20.0M)]

[Times: user=0.05 sys=0.02, real=0.04 secs]

...

[GC concurrent-mark-abort]

復制代碼

(4)、重新標記引起全局停頓

[Ref Proc: 0.3 ms]

復制代碼

(5)、重新標記后進行獨占清理

4.088: [GC cleanup 117M->106M(138M), 0.0015198 secs]

復制代碼

(6)、并發清理是并發執行的,會根據獨占清理階段計算出的每個區域的存活對象數量,直接回收已經不包含存活對象的區域。

4.090: [GC concurrent-cleanup-start]

并發清理階段開始,它釋放被發現為空的區域(不包含任何的活躍數據的區域),在上一個stop-the-world階段期間。

4.091: [GC concurrent-cleanup-end, 0.0002721]

并發清理階段清理空的區域用時0.0002721秒。

復制代碼

關于G1日志,想要知道所有內容的,可以看這篇文章,適合查詢:

blog.csdn.net/zhanggang80…

混合回收

在并發標記周期中,雖然有部分對象被回收,但是從整體上來說,回收的比例是相當低的。但是在并發標記周期后,G1已經明確知道哪些區域含有比較多的垃圾對象了,在混合階段,就是對這些區域進行回收的。當然,會優先回收垃圾比例比較高的區域。因為回收這些區域的性價比比較高。

G1是指垃圾優先的垃圾回收器,全稱"Garbage First Garbage Collector".

在混合回收中,即會執行正常年輕代GC,也會選取被標記的老年代區域進行回收,它同時處理了新生代和老年代。因為新生代GC的原因,eden區域必然被清空,此外,如下圖,有兩塊區域被標記為G的垃圾回收比例最高的區域被清理。被清理區域的存活對象會被移動到其他區域,這樣的好處是可以減少空間碎片。f732e57dfe70393ad4b9c2ac8d3ed81c.png

混合GC產生如下日志:7c4dce1ba788f5250c9a56a65325d9dc.png

混合GC執行多次,直到回收了足夠多的內存空間,觸發一次新生代GC。新生代GC后,有可能會發生一次并發標記周期的清理,最后又引起混合GC。整個流程見下圖:

3b29968bd593a147fe93044001c6dd78.png

必要時的Full GC

與CMS類似,并發收集由于讓應用和GC線程交替工作,因此總是不能避免在特別的繁忙場合在回收過程導致內存不足,此時,G1也會執行一個Full GC回收。

d53e9ab6ab47a4a53896c2f925abd699.png

此外,在混合GC和新生代GC時,survivor與老年代無法無法容納幸存對象,都會導致Full GC產生

完整的G1日志分析

56e4a6dea280d4859579f20c0c576af8.png

4d3ad712ec3e761ffd70577a9dc3a723.png

44b1c8a589b1f898aff1460c0cc11333.png

ccc94adb40f5d9382a37bfe73dcc8d4c.png

3c27db9a59cb1771998bbc2ecae5b2e5.png

ec673f2ba55eeb86687a7e5573252200.png

G1 的相關參數

對于Gl收集器,可以使用-XX:+UseGIGC標記打開Gl收集器開關,對Gt收集器進行設置時,最重要的一 個參數就是-XX :MaxGCPauseMillis,它用于指定目標最大停頓時間。如果任何一次停頓超過這個設置值時,Gl就會嘗試調整新生代和老年代的比例、調整堆大小、調整晉升年齡等手段,試圖達到預設目標。對于性能調優來說,

有時候,總是魚和熊掌不可兼得的,如果停頓時間縮短,對千新生代來說,這意味著很可能要增加新生代GC的次數,GC反而會變得更加頻繁。對于老年代區域來說,為了獲得更短的停頓時間,那么在混合GC收集時,一次收集的區域數量也會變少,這樣無疑增加了進行FullGC的可能性。另外一個重要的參數是-XX :ParallelGCThreads, 它用于設置并行回收時,GC的工作線程數量。

此外,-XX:InitiatingHeapOccupancyPercent參數可以指定當整個堆使用率達到多少時,觸發并發標記周期的執行。默認值是45, 即當整個堆占用率達到45%時,執行并發標記周期。 InitiatingHeapOccupancyPercent 一 旦設置,始終都不會被G l收集器修改,這意味著G I收集器不會試圖改變這個值,來滿足MaxGCPause汕His的目標。如果InitiatingHeapOccupancyPercent值設置偏大,會導致并發周期遲遲得不到啟動,那么引起Full GC的可能性也大大增加,反之,一 個過小的 InitiatingHeapOccupancyPercent值,會使得并發周期非常頻繁,大整 GC 線程搶占CPU, 會導致應用程序的性能有所下降。

來自《深入理解JVM虛擬機》JVM高級特性與最佳實現。

《實戰java虛擬機》復制代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533937.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533937.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533937.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python爬取嗶哩嗶哩視頻_Python實現視頻爬取下載

注:源內容來自公眾號【python學習開發】一般情況下我們使用爬蟲更多的是對數據或者圖片進行爬取,今天在這里和大家分享一下關于使用爬蟲技術來進行視頻下載的方法,不僅可以方便的下載一些體積小的視頻,針對大容量的視頻下載同樣試用。接下來我們來介紹此次爬取視頻過…

java約瑟夫環pta上_cdoj525-猴子選大王 (約瑟夫環)

約瑟夫斯問題問題有時候也被描述成猴子選大王問題,題目如下.(最后會貼上約瑟夫問題的來歷) 一群猴子排成一圈,按1,2,…,n依次編號. 然后從第1只開始數,數到第m只,把它踢出圈,從它后面再開始數,再數到第m只,在把它踢出去…,如此不停的進行下去,直到最后只剩下一只猴子為止,那只猴…

java++記錄+運行_記錄java+testng運行selenium(三)---xml、ini、excel、日志等配置

一: ini文件ini目前只用處存儲瀏覽類型及需要打開的url,ini文件放在configs文件夾下面。讀取ini代碼如下:1 packagetoolskit.documents;23 import java.io.*;4 import java.util.*;56 /**7 * ClassName: ReadIni8 * Author: DingDong9 * D…

python字符串前面加f什么意思_Python 字符串前面加u,r,b,f的含義

1、字符串前加 u例:u"我是含有中文字符組成的字符串。"作用:后面字符串以 Unicode 格式 進行編碼,一般用在中文字符串前面,防止因為源碼儲存格式問題,導致再次使用時出現亂碼。2、字符串前加 r例&#xff1a…

mysql居左查詢abcd_MySql速查手冊

索引定義索引用來快速地尋找那些具有特定值的記錄,所有MySQL索引都以B樹的形式保存。就像是數據的目錄。索引類型唯一索引主鍵索引B-Tree普通索引R-Tree聯合索引Hash全文索引FullText在mysql中fulltext索引只針對myisam生效。符合索引對于創建的多列索引(復合索引)&…

和python哪個容易胖_為什么有些人特別容易胖?

7種人,最容易被肥胖盯上,其中有你嗎?胖,總是來得猝不及防,肥肉也總是不知不覺地長出來……許多胖友對自己的身材老摸不著腦,其實,長胖都是有跡可循的!正如下面這7類人,就…

loadrunner 錯誤: 無法找到 java.exe_LoadRunner錯誤及解決方法總結

1. error:missing newline in d:\loadrunner\name.dat場景執行時報error:missing newline in d:\loadrunner\name.dat第二次執行不報兩個解決辦法:第一:如果參數不是很多的話,不要打開記事本去編輯參數,就直接在LR提供的參數的表格…

gif透明背景動畫_【超實用干貨! 】iPad上的動畫App大推薦

作者/立夏編輯/彼方大家好,我是立夏。大概在兩年前吧我為大家寫過幾款動畫APP的評測,這一次我也想給大家推薦一些我的新寵,供大家參考。我在這里就不過多提及如Animation Desk、Procreate或是Callipeg之類知名度相對更高一些的動畫App了&…

python框架是干什么的_django框架是干什么的

django(Python Web 框架)Django是一個開放源代碼的Web應用框架,由Python寫成。采用了MTV的框架模式,即模型M,視圖V和模版T。它最初是被開發來用于管理勞倫斯出版集團旗下的一些以新聞內容為主的網站的,即是CMS(內容管理系統)軟件。…

iphone如何信任軟件_【手機軟件】千禾影院:全新觀影神器,支持安卓+iOS,最新、最全、高清、免費!...

Hello,大家好,我是春哥!每天記得打卡哦!感謝每一位小伙伴們的關注和支持!免責聲明大部分資源來源于網絡,僅供學習和交流使用,如有侵權請聯系我們刪除。每期文章末尾都會有關鍵詞,在公眾號發消息…

Java小魔女芭芭拉_沉迷蘑菇不可自拔,黏土人《小魔女學園》蘇西·曼芭芭拉 圖賞...

GOOD SMILE出品的黏土人系列手辦新作——《小魔女學園》蘇西曼芭芭拉,已經開始接受預定了。這款黏土人的原型師是來自中國上海的陳天,售價4167日元,預計2018年4月發售。蘇西是主人公亞可的室友,她是從東南亞來的身份不明的魔女。熱…

java int相除向上取整_java實戰項目常用類,Date、Calendar、BigDecimal、Math、UUID

Java開發中經常用到的類和方法,以下主要就日期是時間處理、金融數字處理、數學計算、隨機數、MD5加密等。java.util.Date類java.util 包提供了 Date 類來封裝當前的日期和時間。 Date 類提供兩個構造函數來實例化 Date 對象。日期時間的本質是一個long,它…

python四級中考有用的_一位中考生家長的后悔藥:考前30多天,千萬別做這7件傻事...

中考即將來臨,考后必定是幾家歡樂幾家愁,有慶幸的、有后悔的。中考前的幾個月到底應該怎么過?考前考中需要注意什么?家長做哪些事情是畫蛇添足的。今天給大家推薦一位“中考失敗”學子父親的自白,其中有對優秀兒子的心疼&#xf…

R語言中dim函數_R語言--向量化計算(apply族函數)

R語言最優秀的是它的向量化編程,這其中apply族函數扮演了非常重要的角色。apply族函數是由apply、sapply、lapply、mapply、tapply等函數組成的。熟練使用apply族函數,能夠簡化程序,提高代碼的運算速度。軟件&環境win10 64bitR 3.6.1appl…

php+mysql記事本_一個簡單記事本php操作mysql輔助類創建

//SqlHelper.class.phpconnmysql_connect($this->host,$this->user,$this->passwrd); if(!$this->conn){ die("連接失敗".mysql_error()); } mysql_select_db($this->db); mysql_query("set names utf8"); } //增刪改 function execute_dml…

python init方法做了什么_Python類方法、__new__方法和__init__方法分別是什么

Python類方法、__new__方法和__init__方法分別是什么發布時間:2020-09-03 15:24:06來源:億速云閱讀:104作者:小新這篇文章主要介紹Python類方法、__new__方法和__init__方法分別是什么,文中介紹的非常詳細,…

谷歌瀏覽器中文版_中國科學家設計超薄指尖傳感器,厚度不到A4紙五分之一 / 谷歌發布地圖時光機:百年前,你家街道啥樣?/ AI看圖說話首超人類...

關注我們了解計算機視覺最新動態 !動態先覽1中國科學家設計超薄指尖傳感器,厚度不到A4紙五分之一2谷歌發布地圖「時光機」:100年前,你家街道長啥樣?3仿真環境跟車2分鐘,就讓自動駕駛系統撞上馬路牙子&#…

300小時成為java程序員_直擊面試現場: Java程序員3輪6小時面試, 成功拿到阿里offer!...

原標題:直擊面試現場: Java程序員3輪6小時面試, 成功拿到阿里offer!今天給大家分享一位Java程序員小伙去阿里應聘的經歷!從Java開發要掌握的技術來講,前面已經說得差不多了。我主要想從面試者的角度談一談看法。如果是我面試,就給…

python 判斷每月最后一天_python獲取某年中每個月的第一天和最后一天的兩種方法...

搜索關鍵字:python get every first day of month參考解答:方法一:>>> import calendar>>> calendar.monthrange(2002,1)(1, 31)>>> calendar.monthrange(2008,2)(4, 29)>>> calendar.monthrange(2100,2…

anaconda python3.8目錄_MacBook Pro 安裝anaconda、配置環境

新入手了MacBook Pro,iOS系統還不算非常熟練...作為一個新手程序員,在python開發道路上的學習就從安裝環境開始吧:1、下載安裝包2、安裝過程一路同意or繼續...不過,mac上彈出不允許在當前路徑安裝,那么選擇自定義安裝路…