www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]young gc、old gc、full gc、mixed gc 傻傻分不清?這個(gè)問題的前置條件是你得知道 GC 分代,為什么分代。這個(gè)在之前文章提了,不清楚的可以去看看?,F(xiàn)在我們來回答一下這個(gè)問題。

young gc、old gc、full gc、mixed gc 傻傻分不清?

這個(gè)問題的前置條件是你得知道 GC 分代,為什么分代。這個(gè)在之前文章提了,不清楚的可以去看看。

現(xiàn)在我們來回答一下這個(gè)問題。

其實(shí) GC 分為兩大類,分別是 Partial GC 和 Full GC。

Partial GC 即部分收集,分為 young gc、old gc、mixed gc。

  • young gc:指的是單單收集年輕代的 GC。
  • old gc:指的是單單收集老年代的 GC。
  • mixed gc:這個(gè)是 G1 收集器特有的,指的是收集整個(gè)年輕代和部分老年代的 GC。

Full GC 即整堆回收,指的是收取整個(gè)堆,包括年輕代、老年代,如果有永久代的話還包括永久代。

其實(shí)還有 Major GC 這個(gè)名詞,在《深入理解Java虛擬機(jī)》中這個(gè)名詞指代的是單單老年代的 GC,也就是和 old gc 等價(jià)的,不過也有很多資料認(rèn)為其是和 full gc 等價(jià)的。

還有 Minor GC,其指的就是年輕代的 gc。

young gc 觸發(fā)條件是什么?

大致上可以認(rèn)為在年輕代的 eden 快要被占滿的時(shí)候會(huì)觸發(fā) young gc。

為什么要說大致上呢?因?yàn)橛幸恍┦占鞯幕厥諏?shí)現(xiàn)是在 full gc 前會(huì)讓先執(zhí)行以下 young gc。

比如 Parallel Scavenge,不過有參數(shù)可以調(diào)整讓其不進(jìn)行 young gc。

可能還有別的實(shí)現(xiàn)也有這種操作,不過正常情況下就當(dāng)做 eden 區(qū)快滿了即可。

eden 快滿的觸發(fā)因素有兩個(gè),一個(gè)是為對(duì)象分配內(nèi)存不夠,一個(gè)是為 TLAB 分配內(nèi)存不夠。

full gc 觸發(fā)條件有哪些?

這個(gè)觸發(fā)條件稍微有點(diǎn)多,我們來看下。

  • 在要進(jìn)行 young gc 的時(shí)候,根據(jù)之前統(tǒng)計(jì)數(shù)據(jù)發(fā)現(xiàn)年輕代平均晉升大小比現(xiàn)在老年代剩余空間要大,那就會(huì)觸發(fā) full gc。
  • 有永久代的話如果永久代滿了也會(huì)觸發(fā) full gc。
  • 老年代空間不足,大對(duì)象直接在老年代申請(qǐng)分配,如果此時(shí)老年代空間不足則會(huì)觸發(fā) full gc。
  • 擔(dān)保失敗即 promotion failure,新生代的 to 區(qū)放不下從 eden 和 from 拷貝過來對(duì)象,或者新生代對(duì)象 gc 年齡到達(dá)閾值需要晉升這兩種情況,老年代如果放不下的話都會(huì)觸發(fā) full gc。
  • 執(zhí)行 System.gc()、jmap -dump 等命令會(huì)觸發(fā) full gc。

知道 TLAB 嗎?來說說看

這個(gè)得從內(nèi)存申請(qǐng)說起。

一般而言生成對(duì)象需要向堆中的新生代申請(qǐng)內(nèi)存空間,而堆又是全局共享的,像新生代內(nèi)存又是規(guī)整的,是通過一個(gè)指針來劃分的。

炸了!一口氣問了我18個(gè)JVM問題!

內(nèi)存是緊湊的,新對(duì)象創(chuàng)建指針就右移對(duì)象大小 size 即可,這叫指針加法(bump [up] the pointer)。

可想而知如果多個(gè)線程都在分配對(duì)象,那么這個(gè)指針就會(huì)成為熱點(diǎn)資源,需要互斥那分配的效率就低了。

于是搞了個(gè) TLAB(Thread Local Allocation Buffer),為一個(gè)線程分配的內(nèi)存申請(qǐng)區(qū)域。

這個(gè)區(qū)域只允許這一個(gè)線程申請(qǐng)分配對(duì)象,允許所有線程訪問這塊內(nèi)存區(qū)域。

TLAB 的思想其實(shí)很簡單,就是劃一塊區(qū)域給一個(gè)線程,這樣每個(gè)線程只需要在自己的那畝地申請(qǐng)對(duì)象內(nèi)存,不需要爭搶熱點(diǎn)指針。

當(dāng)這塊內(nèi)存用完了之后再去申請(qǐng)即可。

這種思想其實(shí)很常見,比如分布式發(fā)號(hào)器,每次不會(huì)一個(gè)一個(gè)號(hào)的取,會(huì)取一批號(hào),用完之后再去申請(qǐng)一批。

炸了!一口氣問了我18個(gè)JVM問題!

可以看到每個(gè)線程有自己的一塊內(nèi)存分配區(qū)域,短一點(diǎn)的箭頭代表 TLAB 內(nèi)部的分配指針。

如果這塊區(qū)域用完了再去申請(qǐng)即可。

不過每次申請(qǐng)的大小不固定,會(huì)根據(jù)該線程啟動(dòng)到現(xiàn)在的歷史信息來調(diào)整,比如這個(gè)線程一直在分配內(nèi)存那么 TLAB 就大一些,如果這個(gè)線程基本上不會(huì)申請(qǐng)分配內(nèi)存那 TLAB 就小一些。

還有 TLAB 會(huì)浪費(fèi)空間,我們來看下這個(gè)圖。

炸了!一口氣問了我18個(gè)JVM問題!

可以看到 TLAB 內(nèi)部只剩一格大小,申請(qǐng)的對(duì)象需要兩格,這時(shí)候需要再申請(qǐng)一塊 TLAB ,之前的那一格就浪費(fèi)了。

在 HotSpot 中會(huì)生成一個(gè)填充對(duì)象來填滿這一塊,因?yàn)槎研枰€性遍歷,遍歷的流程是通過對(duì)象頭得知對(duì)象的大小,然后跳過這個(gè)大小就能找到下一個(gè)對(duì)象,所以不能有空洞。

當(dāng)然也可以通過空閑鏈表等外部記錄方式來實(shí)現(xiàn)遍歷。

還有 TLAB 只能分配小對(duì)象,大的對(duì)象還是需要在共享的 eden 區(qū)分配

所以總的來說 TLAB 是為了避免對(duì)象分配時(shí)的競爭而設(shè)計(jì)的。

那 PLAB 知道嗎?

可以看到和 TLAB 很像,PLAB 即 Promotion Local Allocation Buffers。

用在年輕代對(duì)象晉升到老年代時(shí)。

在多線程并行執(zhí)行 YGC 時(shí),可能有很多對(duì)象需要晉升到老年代,此時(shí)老年代的指針就“熱”起來了,于是搞了個(gè) PLAB。

先從老年代 freelist(空閑鏈表) 申請(qǐng)一塊空間,然后在這一塊空間中就可以通過指針加法(bump the pointer)來分配內(nèi)存,這樣對(duì) freelist 競爭也少了,分配空間也快了。

炸了!一口氣問了我18個(gè)JVM問題!

大致就是上圖這么個(gè)思想,每個(gè)線程先申請(qǐng)一塊作為 PLAB ,然后在這一塊內(nèi)存里面分配晉升的對(duì)象。

這和 TLAB 的思想相似。

產(chǎn)生 concurrent mode failure 真正的原因

《深入理解Java虛擬機(jī)》:由于CMS收集器無法處理“浮動(dòng)垃圾”(FloatingGarbage),有可能出現(xiàn)“Con-current Mode Failure”失敗進(jìn)而導(dǎo)致另一次完全“Stop The World”的Full GC的產(chǎn)生。

這段話的意思是因?yàn)閽佭@個(gè)錯(cuò)而導(dǎo)致一次 Full GC。

實(shí)際上是 Full GC 導(dǎo)致拋這個(gè)錯(cuò),我們來看一下源碼,版本是 openjdk-8。

首先搜一下這個(gè)錯(cuò)。

炸了!一口氣問了我18個(gè)JVM問題!

再找找看 ?report_concurrent_mode_interruption 被誰調(diào)用。

查到是在 void CMSCollector::acquire_control_and_collect(...) 這個(gè)方法中被調(diào)用的。

炸了!一口氣問了我18個(gè)JVM問題!

再來看看 first_state :CollectorState first_state = _collectorState;

炸了!一口氣問了我18個(gè)JVM問題!

看枚舉已經(jīng)很清楚了,就是在 cms gc 還沒結(jié)束的時(shí)候。

acquire_control_and_collect 這個(gè)方法是 cms 執(zhí)行 foreground gc 的。

cms 分為 ?foreground gc 和 background gc。

foreground 其實(shí)就是 Full gc。

因此是 full gc 的時(shí)候 cms gc 還在進(jìn)行中導(dǎo)致拋這個(gè)錯(cuò)。

究其原因是因?yàn)榉峙渌俾侍鞂?dǎo)致堆不夠用,回收不過來因此產(chǎn)生 full gc。

也有可能是發(fā)起 cms gc 設(shè)置的堆的閾值太高。

CMS GC 發(fā)生 concurrent mode failure 時(shí)的 full GC 為什么是單線程的?

以下的回答來自 R 大。

因?yàn)闆]足夠開發(fā)資源,偷懶了。就這么簡單。沒有任何技術(shù)上的問題。大公司都自己內(nèi)部做了優(yōu)化。

所以最初怎么會(huì)偷這個(gè)懶的呢?多災(zāi)多難的CMS GC經(jīng)歷了多次動(dòng)蕩。它最初是作為Sun Labs的Exact VM的低延遲GC而設(shè)計(jì)實(shí)現(xiàn)的。

但 Exact VM在與 HotSpot VM爭搶 Sun 的正牌 JVM 的內(nèi)部斗爭中失利,CMS GC 后來就作為 Exact VM 的技術(shù)遺產(chǎn)被移植到了 HotSpot VM上。

就在這個(gè)移植還在進(jìn)行中的時(shí)候,Sun 已經(jīng)開始略顯疲態(tài);到 CMS GC 完全移植到 HotSpot VM 的時(shí)候,Sun 已經(jīng)處于快要不行的階段了。

開發(fā)資源減少,開發(fā)人員流失,當(dāng)時(shí)的 HotSpot VM 開發(fā)組能夠做的事情并不多,只能挑重要的來做。而這個(gè)時(shí)候 Sun Labs 的另一個(gè) GC 實(shí)現(xiàn),Garbage-First GC(G1 GC)已經(jīng)面世。

相比可能在長時(shí)間運(yùn)行后受碎片化影響的 CMS,G1 會(huì)增量式的整理/壓縮堆里的數(shù)據(jù),避免受碎片化影響,因而被認(rèn)為更具潛力。

于是當(dāng)時(shí)本來就不多的開發(fā)資源,一部分還投給了把G1 GC產(chǎn)品化的項(xiàng)目上——結(jié)果也是進(jìn)展緩慢。

畢竟只有一兩個(gè)人在做。所以當(dāng)時(shí)就沒能有足夠開發(fā)資源去打磨 CMS GC 的各種配套設(shè)施的細(xì)節(jié),配套的備份 full GC 的并行化也就耽擱了下來。

但肯定會(huì)有同學(xué)抱有疑問:HotSpot VM不是已經(jīng)有并行GC了么?而且還有好幾個(gè)?

讓我們來看看:

  • ParNew:并行的young gen GC,不負(fù)責(zé)收集old gen。
  • Parallel GC(ParallelScavenge):并行的young gen GC,與ParNew相似但不兼容;同樣不負(fù)責(zé)收集old gen。
  • ParallelOld GC(PSCompact):并行的full GC,但與ParNew / CMS不兼容。

所以…就是這么一回事。

HotSpot VM 確實(shí)是已經(jīng)有并行 GC 了,但兩個(gè)是只負(fù)責(zé)在 young GC 時(shí)收集 young gen 的,這倆之中還只有 ParNew 能跟 CMS 搭配使用;

而并行 full GC 雖然有一個(gè) ParallelOld,但卻與 CMS GC 不兼容所以無法作為它的備份 full GC使用。

為什么有些新老年代的收集器不能組合使用比如 ParNew 和 Parallel Old?

炸了!一口氣問了我18個(gè)JVM問題!

這張圖是 2008 年 HostSpot 一位 GC 組成員畫的,那時(shí)候 G1 還沒問世,在研發(fā)中,所以畫了個(gè)問號(hào)在上面。

里面的回答是 :

"ParNew" is written in a style... "Parallel Old" is not written in the "ParNew" style

HotSpot VM 自身的分代收集器實(shí)現(xiàn)有一套框架,只有在框架內(nèi)的實(shí)現(xiàn)才能互相搭配使用。

而有個(gè)開發(fā)他不想按照這個(gè)框架實(shí)現(xiàn),自己寫了個(gè),測試的成績還不錯(cuò)后來被 ?HotSpot VM 給吸收了,這就導(dǎo)致了不兼容。

我之前看到一個(gè)回答解釋的很形象:就像動(dòng)車組車頭帶不了綠皮車廂一樣,電氣,掛鉤啥的都不匹配。

新生代的 GC 如何避免全堆掃描?

在常見的分代 GC 中就是利用記憶集來實(shí)現(xiàn)的,記錄可能存在的老年代中有新生代的引用的對(duì)象地址,來避免全堆掃描。

炸了!一口氣問了我18個(gè)JVM問題!

上圖有個(gè)對(duì)象精度的,一個(gè)是卡精度的,卡精度的叫卡表。

把堆中分為很多塊,每塊 512 字節(jié)(卡頁),用字節(jié)數(shù)組來中的一個(gè)元素來表示某一塊,1表示臟塊,里面存在跨代引用。

炸了!一口氣問了我18個(gè)JVM問題!

在 Hotspot 中的實(shí)現(xiàn)是卡表,是通過寫后屏障維護(hù)的,偽代碼如下。

炸了!一口氣問了我18個(gè)JVM問題!

cms 中需要記錄老年代指向年輕代的引用,但是寫屏障的實(shí)現(xiàn)并沒有做任何條件的過濾。

不判斷當(dāng)前對(duì)象是老年代對(duì)象且引用的是新生代對(duì)象才會(huì)標(biāo)記對(duì)應(yīng)的卡表為臟。

只要是引用賦值都會(huì)把對(duì)象的卡標(biāo)記為臟,當(dāng)然YGC掃描的時(shí)候只會(huì)掃老年代的卡表。

這樣做是減少寫屏障帶來的消耗,畢竟引用的賦值非常的頻繁。

那 cms 的記憶集和 G1 的記憶集有什么不一樣?

cms 的記憶集的實(shí)現(xiàn)是卡表即 card table。

通常實(shí)現(xiàn)的記憶集是 points-out 的,我們知道記憶集是用來記錄非收集區(qū)域指向收集區(qū)域的跨代引用,它的主語其實(shí)是非收集區(qū)域,所以是 points-out 的。

在 cms 中只有老年代指向年輕代的卡表,用于年輕代 gc。

而 G1 是基于 region 的,所以在 points-out 的卡表之上還加了個(gè) points-into 的結(jié)構(gòu)。

因?yàn)橐粋€(gè) region 需要知道有哪些別的 region 有指向自己的指針,然后還需要知道這些指針在哪些 card 中。

其實(shí) G1 的記憶集就是個(gè) hash table,key 就是別的 region 的起始地址,然后 value 是一個(gè)集合,里面存儲(chǔ)這 card table 的 index。

我們來看下這個(gè)圖就很清晰了。

炸了!一口氣問了我18個(gè)JVM問題!

像每次引用字段的賦值都需要維護(hù)記憶集開銷很大,所以 G1 的實(shí)現(xiàn)利用了 logging write barrier(下文會(huì)介紹)。

也是異步思想,會(huì)先將修改記錄到隊(duì)列中,當(dāng)隊(duì)列超過一定閾值由后臺(tái)線程取出遍歷來更新記憶集。

為什么 G1 不維護(hù)年輕代到老年代的記憶集?

G1 分了 young GC 和 mixed gc。

young gc 會(huì)選取所有年輕代的 region 進(jìn)行收集。

midex gc 會(huì)選取所有年輕代的 region 和一些收集收益高的老年代 region 進(jìn)行收集。

所以年輕代的 region 都在收集范圍內(nèi),所以不需要額外記錄年輕代到老年代的跨代引用

cms 和 G1 為了維持并發(fā)的正確性分別用了什么手段?

之前文章分析到了并發(fā)執(zhí)行漏標(biāo)的兩個(gè)充分必要條件是:

  1. 將新對(duì)象插入已掃描完畢的對(duì)象中,即插入黑色對(duì)象到白色對(duì)象的引用。

  2. 刪除了灰色對(duì)象到白色對(duì)象的引用。

cms 和 g1 分別通過增量更新和 SATB 來打破這兩個(gè)充分必要條件,維持了 GC 線程與應(yīng)用線程并發(fā)的正確性。

cms 用了增量更新(Incremental update),打破了第一個(gè)條件,通過寫屏障將插入的白色對(duì)象標(biāo)記成灰色,即加入到標(biāo)記棧中,在 remark 階段再掃描,防止漏標(biāo)情況。

G1 用了 SATB(snapshot-at-the-beginning),打破了第二個(gè)條件,會(huì)通過寫屏障把舊的引用關(guān)系記下來,之后再把舊引用關(guān)系再掃描過。

這個(gè)從英文名詞來看就已經(jīng)很清晰了。講白了就是在 GC 開始時(shí)候如果對(duì)象是存活的就認(rèn)為其存活,等于拍了個(gè)快照。

而且 gc 過程中新分配的對(duì)象也都認(rèn)為是活的。每個(gè) region 會(huì)維持 TAMS (top at mark start)指針,分別是 prevTAMS 和 nextTAMS 分別標(biāo)記兩次并發(fā)標(biāo)記開始時(shí)候 Top 指針的位置。

Top 指針就是 region 中最新分配對(duì)象的位置,所以 nextTAMS 和 Top 之間區(qū)域的對(duì)象都是新分配的對(duì)象都認(rèn)為其是存活的即可。

炸了!一口氣問了我18個(gè)JVM問題!

而利用增量更新的 cms 在 remark 階段需要重新所有線程棧和整個(gè)年輕代,因?yàn)榈扔谥暗母行略?,所以需要重新掃描過,如果年輕代的對(duì)象很多的話會(huì)比較耗時(shí)。

要注意這階段是 STW 的,很關(guān)鍵,所以 CMS 也提供了一個(gè) CMSScavengeBeforeRemark 參數(shù),來強(qiáng)制 remark 階段之前來一次 YGC。

而 g1 通過 SATB 的話在最終標(biāo)記階段只需要掃描 SATB 記錄的舊引用即可,從這方面來說會(huì)比 cms 快,但是也因?yàn)檫@樣浮動(dòng)垃圾會(huì)比 cms 多。

什么是 logging write barrier ?

寫屏障其實(shí)耗的是應(yīng)用程序的性能,是在引用賦值的時(shí)候執(zhí)行的邏輯,這個(gè)操作非常的頻繁,因此就搞了個(gè) logging write barrier。

把寫屏障要執(zhí)行的一些邏輯搬運(yùn)到后臺(tái)線程執(zhí)行,來減輕對(duì)應(yīng)用程序的影響。

在寫屏障里只需要記錄一個(gè) log 信息到一個(gè)隊(duì)列中,然后別的后臺(tái)線程會(huì)從隊(duì)列中取出信息來完成后續(xù)的操作,其實(shí)就是異步思想。

像 SATB write barrier ,每個(gè) Java 線程有一個(gè)獨(dú)立的、定長的 SATBMarkQueue,在寫屏障里只把舊引用壓入該隊(duì)列中。滿了之后會(huì)加到全局 SATBMarkQueueSet。

炸了!一口氣問了我18個(gè)JVM問題!

后臺(tái)線程會(huì)掃描,如果超過一定閾值就會(huì)處理,開始 tracing。

在維護(hù)記憶集的寫屏障也用了 logging write barrier 。

簡單說下 G1 回收流程

G1 從大局上看分為兩大階段,分別是并發(fā)標(biāo)記和對(duì)象拷貝。

并發(fā)標(biāo)記是基于 STAB 的,可以分為四大階段:

1、初始標(biāo)記(initial marking,這個(gè)階段是 STW 的,掃描根集合,標(biāo)記根直接可達(dá)的對(duì)象即可。在G1中標(biāo)記對(duì)象是利用外部的bitmap來記錄,而不是對(duì)象頭。

2、并發(fā)階段(concurrent marking),這個(gè)階段和應(yīng)用線程并發(fā),從上一步標(biāo)記的根直接可達(dá)對(duì)象開始進(jìn)行 tracing,遞歸掃描所有可達(dá)對(duì)象。STAB 也會(huì)在這個(gè)階段記錄著變更的引用。

3、最終標(biāo)記(final marking, 這個(gè)階段是 STW 的,處理 STAB 中的引用。

4、清理階段(clenaup),這個(gè)階段是 STW 的,根據(jù)標(biāo)記的 bitmap 統(tǒng)計(jì)每個(gè) region 存活對(duì)象的多少,如果有完全沒存活的 region 則整體回收。

對(duì)象拷貝階段(evacuation,這個(gè)階段是 STW 的。

根據(jù)標(biāo)記結(jié)果選擇合適的 reigon 組成收集集合(collection set 即 CSet),然后將 CSet 存活對(duì)象拷貝到新 region 中。

G1 的瓶頸在于對(duì)象拷貝階段,需要花較多的瓶頸來轉(zhuǎn)移對(duì)象。

簡單說下 cms 回收流程

其實(shí)從之前問題的 CollectorState 枚舉可以得知幾個(gè)流程了。

1、初始標(biāo)記(initial mark),這個(gè)階段是 STW 的,掃描根集合,標(biāo)記根直接可達(dá)的對(duì)象即可。

2、并發(fā)標(biāo)記(Concurrent marking),這個(gè)階段和應(yīng)用線程并發(fā),從上一步標(biāo)記的根直接可達(dá)對(duì)象開始進(jìn)行 tracing,遞歸掃描所有可達(dá)對(duì)象。

3、并發(fā)預(yù)清理(Concurrent precleaning),這個(gè)階段和應(yīng)用線程并發(fā),就是想幫重新標(biāo)記階段先做點(diǎn)工作,掃描一下卡表臟的區(qū)域和新晉升到老年代的對(duì)象等,因?yàn)橹匦聵?biāo)記是 STW 的,所以分擔(dān)一點(diǎn)。

4、可中斷的預(yù)清理階段(AbortablePreclean),這個(gè)和上一個(gè)階段基本上一致,就是為了分擔(dān)重新標(biāo)記標(biāo)記的工作。

5、重新標(biāo)記(remark),這個(gè)階段是 STW 的,因?yàn)椴l(fā)階段引用關(guān)系會(huì)發(fā)生變化,所以要重新遍歷一遍新生代對(duì)象、Gc Roots、卡表等,來修正標(biāo)記。

6、并發(fā)清理(Concurrent sweeping),這個(gè)階段和應(yīng)用線程并發(fā),用于清理垃圾。

7、并發(fā)重置(Concurrent reset),這個(gè)階段和應(yīng)用線程并發(fā),重置 cms 內(nèi)部狀態(tài)。

cms 的瓶頸就在于重新標(biāo)記階段,需要較長花費(fèi)時(shí)間來進(jìn)行重新掃描。

cms 寫屏障又是維護(hù)卡表,又得維護(hù)增量更新?

卡表其實(shí)只有一份,又得用來支持 YGC 又得支持 CMS 并發(fā)時(shí)的增量更新肯定是不夠的。

每次 YGC 都會(huì)掃描重置卡表,這樣增量更新的記錄就被清理了。

所以還搞了個(gè) mod-union table,在并發(fā)標(biāo)記時(shí),如果發(fā)生 YGC 需要重置卡表的記錄時(shí),就會(huì)更新 ?mod-union table 對(duì)應(yīng)的位置。

這樣 cms 重新標(biāo)記階段就能結(jié)合當(dāng)時(shí)的卡表和 ?mod-union table 來處理增量更新,防止漏標(biāo)對(duì)象了。

GC 調(diào)優(yōu)的兩大目標(biāo)是啥?

分別是最短暫停時(shí)間和吞吐量。

最短暫停時(shí)間:因?yàn)?GC 會(huì) STW 暫停所有應(yīng)用線程,這時(shí)候?qū)τ谟脩舳跃偷扔诳D了,因此對(duì)于時(shí)延敏感的應(yīng)用來說減少 STW 的時(shí)間是關(guān)鍵。

吞吐量:對(duì)于一些對(duì)時(shí)延不敏感的應(yīng)用比如一些后臺(tái)計(jì)算應(yīng)用來說,吞吐量是關(guān)注的重點(diǎn),它們不關(guān)注每次 GC 停頓的時(shí)間,只關(guān)注總的停頓時(shí)間少,吞吐量高。

舉個(gè)例子:

方案一:每次 GC 停頓 100 ms,每秒停頓 5 次。

方案二:每次 GC 停頓 200 ms,每秒停頓 2 次。

兩個(gè)方案相對(duì)而言第一個(gè)時(shí)延低,第二個(gè)吞吐高,基本上兩者不可兼得。

所以調(diào)優(yōu)時(shí)候需要明確應(yīng)用的目標(biāo)

GC 如何調(diào)優(yōu)

這個(gè)問題在面試中很容易問到,抓住核心回答。

現(xiàn)在都是分代 GC,調(diào)優(yōu)的思路就是盡量讓對(duì)象在新生代就被回收,防止過多的對(duì)象晉升到老年代,減少大對(duì)象的分配。

需要平衡分代的大小、垃圾回收的次數(shù)和停頓時(shí)間。

需要對(duì) GC 進(jìn)行完整的監(jiān)控,監(jiān)控各年代占用大小、YGC 觸發(fā)頻率、Full GC 觸發(fā)頻率,對(duì)象分配速率等等。

然后根據(jù)實(shí)際情況進(jìn)行調(diào)優(yōu)。

比如進(jìn)行了莫名其妙的 Full GC,有可能是某個(gè)第三方庫調(diào)了 System.gc。

Full GC 頻繁可能是 CMS GC 觸發(fā)內(nèi)存閾值過低,導(dǎo)致對(duì)象分配不過來。

還有對(duì)象年齡晉升的閾值、survivor 過小等等,具體情況還是得具體分析,反正核心是不變的。

最后

其實(shí)還有關(guān)于 ZGC 的內(nèi)容沒有分析,別急, ZGC 的文章已經(jīng)寫了一半了,之后會(huì)發(fā)。

有關(guān) GC 的問題在面試中還是很常見的,其實(shí)來來回回就那么幾樣?xùn)|西,記得我提到的抓住核心即可。

當(dāng)然如果你有實(shí)際調(diào)優(yōu)經(jīng)歷那更可,所以要抓住工作中的機(jī)會(huì),如果發(fā)生異常情況請(qǐng)積極參與,然后勤加思考,這可都是實(shí)打?qū)嵉膶?shí)戰(zhàn)經(jīng)歷。

當(dāng)然如果你想知道更多的 GC 細(xì)節(jié)那就看源碼吧,源碼之中無秘密。

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

炸了!一口氣問了我18個(gè)JVM問題!

炸了!一口氣問了我18個(gè)JVM問題!

炸了!一口氣問了我18個(gè)JVM問題!

長按訂閱更多精彩▼

炸了!一口氣問了我18個(gè)JVM問題!

如有收獲,點(diǎn)個(gè)在看,誠摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉