精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

老大難的GC原理及調(diào)優(yōu),這全說清楚了

原創(chuàng)
開發(fā) 前端
本文介紹 GC 基礎(chǔ)原理和理論,GC 調(diào)優(yōu)方法思路和方法,基于 Hotspot jdk1.8,學(xué)習(xí)之后你將了解如何對生產(chǎn)系統(tǒng)出現(xiàn)的 GC 問題進(jìn)行排查解決。

【51CTO.com原創(chuàng)稿件】本文介紹 GC 基礎(chǔ)原理和理論,GC 調(diào)優(yōu)方法思路和方法,基于 Hotspot jdk1.8,學(xué)習(xí)之后你將了解如何對生產(chǎn)系統(tǒng)出現(xiàn)的 GC 問題進(jìn)行排查解決。

[[277953]] 

圖片來自 Pexels

內(nèi)容主要如下:

  • GC 基礎(chǔ)原理,涉及調(diào)優(yōu)目標(biāo),GC 事件分類、JVM 內(nèi)存分配策略、GC 日志分析等。
  • CMS 原理及調(diào)優(yōu)。
  • G1 原理及調(diào)優(yōu)。
  • GC 問題排查和解決思路。

GC 基礎(chǔ)原理

GC 調(diào)優(yōu)目標(biāo)

大多數(shù)情況下對 Java 程序進(jìn)行 GC 調(diào)優(yōu),主要關(guān)注兩個目標(biāo):

  • 響應(yīng)速度(Responsiveness):響應(yīng)速度指程序或系統(tǒng)對一個請求的響應(yīng)有多迅速。

比如,用戶訂單查詢響應(yīng)時間,對響應(yīng)速度要求很高的系統(tǒng),較大的停頓時間是不可接受的。調(diào)優(yōu)的重點(diǎn)是在短的時間內(nèi)快速響應(yīng)。

  • 吞吐量(Throughput):吞吐量關(guān)注在一個特定時間段內(nèi)應(yīng)用系統(tǒng)的最大工作量。

例如每小時批處理系統(tǒng)能完成的任務(wù)數(shù)量,在吞吐量方面優(yōu)化的系統(tǒng),較長的 GC 停頓時間也是可以接受的,因為高吞吐量應(yīng)用更關(guān)心的是如何盡可能快地完成整個任務(wù),不考慮快速響應(yīng)用戶請求。

GC 調(diào)優(yōu)中,GC 導(dǎo)致的應(yīng)用暫停時間影響系統(tǒng)響應(yīng)速度,GC 處理線程的 CPU 使用率影響系統(tǒng)吞吐量。

GC 分代收集算法

現(xiàn)代的垃圾收集器基本都是采用分代收集算法,其主要思想: 將 Java 的堆內(nèi)存邏輯上分成兩塊:新生代、老年代,針對不同存活周期、不同大小的對象采取不同的垃圾回收策略。

 

新生代(Young Generation)

新生代又叫年輕代,大多數(shù)對象在新生代中被創(chuàng)建,很多對象的生命周期很短。

每次新生代的垃圾回收(又稱 Young GC、Minor GC、YGC)后只有少量對象存活,所以使用復(fù)制算法,只需少量的復(fù)制操作成本就可以完成回收。

新生代內(nèi)又分三個區(qū):一個 Eden 區(qū),兩個 Survivor 區(qū)(S0、S1,又稱From Survivor、To Survivor),大部分對象在 Eden 區(qū)中生成。

當(dāng) Eden 區(qū)滿時,還存活的對象將被復(fù)制到兩個 Survivor 區(qū)(中的一個);當(dāng)這個 Survivor 區(qū)滿時,此區(qū)的存活且不滿足晉升到老年代條件的對象將被復(fù)制到另外一個 Survivor 區(qū)。

對象每經(jīng)歷一次復(fù)制,年齡加 1,達(dá)到晉升年齡閾值后,轉(zhuǎn)移到老年代。

老年代(Old Generation)

在新生代中經(jīng)歷了 N 次垃圾回收后仍然存活的對象,就會被放到老年代,該區(qū)域中對象存活率高。老年代的垃圾回收通常使用“標(biāo)記-整理”算法。

GC 事件分類

根據(jù)垃圾收集回收的區(qū)域不同,垃圾收集主要分為:

  • Young GC
  • Old GC
  • Full GC
  • Mixed GC

①Young GC

新生代內(nèi)存的垃圾收集事件稱為 Young GC(又稱 Minor GC),當(dāng) JVM 無法為新對象分配在新生代內(nèi)存空間時總會觸發(fā) Young GC。

比如 Eden 區(qū)占滿時,新對象分配頻率越高,Young GC 的頻率就越高。

Young GC 每次都會引起全線停頓(Stop-The-World),暫停所有的應(yīng)用線程,停頓時間相對老年代 GC 造成的停頓,幾乎可以忽略不計。

②Old GC 、Full GC、Mixed GC

Old GC:只清理老年代空間的 GC 事件,只有 CMS 的并發(fā)收集是這個模式。

Full GC:清理整個堆的 GC 事件,包括新生代、老年代、元空間等 。

Mixed GC:清理整個新生代以及部分老年代的 GC,只有 G1 有這個模式。

GC 日志分析

GC 日志是一個很重要的工具,它準(zhǔn)確記錄了每一次的 GC 的執(zhí)行時間和執(zhí)行結(jié)果,通過分析 GC 日志可以調(diào)優(yōu)堆設(shè)置和 GC 設(shè)置,或者改進(jìn)應(yīng)用程序的對象分配模式。

開啟的 JVM 啟動參數(shù)如下:

  1. -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps 

常見的 Young GC、Full GC 日志含義如下:

 

免費(fèi)的 GC 日志圖形分析工具推薦下面 2 個:

  • GCViewer,下載 jar 包直接運(yùn)行 。
  • gceasy,Web 工具,上傳 GC 日志在線使用。

內(nèi)存分配策略

Java 提供的自動內(nèi)存管理,可以歸結(jié)為解決了對象的內(nèi)存分配和回收的問題。

前面已經(jīng)介紹了內(nèi)存回收,下面介紹幾條最普遍的內(nèi)存分配策略:

①對象優(yōu)先在 Eden 區(qū)分配:大多數(shù)情況下,對象在先新生代 Eden 區(qū)中分配。當(dāng) Eden 區(qū)沒有足夠空間進(jìn)行分配時,虛擬機(jī)將發(fā)起一次 Young GC。

②大對象之間進(jìn)入老年代:JVM 提供了一個對象大小閾值參數(shù)(-XX:PretenureSizeThreshold,默認(rèn)值為 0,代表不管多大都是先在 Eden 中分配內(nèi)存)。

大于參數(shù)設(shè)置的閾值值的對象直接在老年代分配,這樣可以避免對象在 Eden 及兩個 Survivor 直接發(fā)生大內(nèi)存復(fù)制。

③長期存活的對象將進(jìn)入老年代:對象每經(jīng)歷一次垃圾回收,且沒被回收掉,它的年齡就增加 1,大于年齡閾值參數(shù)(-XX:MaxTenuringThreshold,默認(rèn) 15)的對象,將晉升到老年代中。

④空間分配擔(dān)保:當(dāng)進(jìn)行 Young GC 之前,JVM 需要預(yù)估:老年代是否能夠容納 Young GC 后新生代晉升到老年代的存活對象,以確定是否需要提前觸發(fā) GC 回收老年代空間,基于空間分配擔(dān)保策略來計算。

continueSize,老年代最大可用連續(xù)空間:

 

Young GC 之后如果成功(Young GC 后晉升對象能放入老年代),則代表擔(dān)保成功,不用再進(jìn)行 Full GC,提高性能。

如果失敗,則會出現(xiàn)“promotion failed”錯誤,代表擔(dān)保失敗,需要進(jìn)行 Full GC。

⑤動態(tài)年齡判定:新生代對象的年齡可能沒達(dá)到閾值(MaxTenuringThreshold 參數(shù)指定)就晉升老年代。

如果 Young GC 之后,新生代存活對象達(dá)到相同年齡所有對象大小的總和大于任意 Survivor 空間(S0+S1空間)的一半,此時 S0 或者 S1 區(qū)即將容納不了存活的新生代對象。

年齡大于或等于該年齡的對象就可以直接進(jìn)入老年代,無須等到 MaxTenuringThreshold 中要求的年齡。

另外,如果 Young GC 后 S0 或 S1 區(qū)不足以容納:未達(dá)到晉升老年代條件的新生代存活對象,會導(dǎo)致這些存活對象直接進(jìn)入老年代,需要盡量避免。

CMS 原理及調(diào)優(yōu)

名詞解釋

可達(dá)性分析算法:用于判斷對象是否存活,基本思想是通過一系列稱為“GC Root”的對象作為起點(diǎn)(常見的 GC Root 有系統(tǒng)類加載器、棧中的對象、處于激活狀態(tài)的線程等),基于對象引用關(guān)系,從 GC Roots 開始向下搜索,所走過的路徑稱為引用鏈,當(dāng)一個對象到 GC Root 沒有任何引用鏈相連,證明對象不再存活。

Stop The World:GC 過程中分析對象引用關(guān)系,為了保證分析結(jié)果的準(zhǔn)確性,需要通過停頓所有 Java 執(zhí)行線程,保證引用關(guān)系不再動態(tài)變化,該停頓事件稱為 Stop The World(STW)。

Safepoint:代碼執(zhí)行過程中的一些特殊位置,當(dāng)線程執(zhí)行到這些位置的時候,說明虛擬機(jī)當(dāng)前的狀態(tài)是安全的,如果有需要 GC,線程可以在這個位置暫停。

HotSpot 采用主動中斷的方式,讓執(zhí)行線程在運(yùn)行期輪詢是否需要暫停的標(biāo)志,若需要則中斷掛起。

CMS 簡介

CMS(Concurrent Mark and Sweep 并發(fā)-標(biāo)記-清除),是一款基于并發(fā)、使用標(biāo)記清除算法的垃圾回收算法,只針對老年代進(jìn)行垃圾回收。

CMS 收集器工作時,盡可能讓 GC 線程和用戶線程并發(fā)執(zhí)行,以達(dá)到降低 STW 時間的目的。

通過以下命令行參數(shù),啟用 CMS 垃圾收集器:

  1. -XX:+UseConcMarkSweepGC 

值得補(bǔ)充的是,下面介紹到的 CMS GC 是指老年代的 GC,而 Full GC 指的是整個堆的 GC 事件,包括新生代、老年代、元空間等,兩者有所區(qū)分。

新生代垃圾回收

能與 CMS 搭配使用的新生代垃圾收集器有 Serial 收集器和 ParNew 收集器。

這 2 個收集器都采用標(biāo)記復(fù)制算法,都會觸發(fā) STW 事件,停止所有的應(yīng)用線程。不同之處在于,Serial 是單線程執(zhí)行,ParNew 是多線程執(zhí)行。

老年代垃圾回收

 

CMS GC 以獲取最小停頓時間為目的,盡可能減少 STW 時間,可以分為 7 個階段:

階段 1:初始標(biāo)記(Initial Mark)

 

此階段的目標(biāo)是標(biāo)記老年代中所有存活的對象, 包括 GC Root 的直接引用, 以及由新生代中存活對象所引用的對象,觸發(fā)第一次 STW 事件。

這個過程是支持多線程的(JDK7 之前單線程,JDK8 之后并行,可通過參數(shù) CMSParallelInitialMarkEnabled 調(diào)整)。

階段 2:并發(fā)標(biāo)記(Concurrent Mark)

 

此階段 GC 線程和應(yīng)用線程并發(fā)執(zhí)行,遍歷階段 1 初始標(biāo)記出來的存活對象,然后繼續(xù)遞歸標(biāo)記這些對象可達(dá)的對象。

階段 3:并發(fā)預(yù)清理(Concurrent Preclean)

 

此階段 GC 線程和應(yīng)用線程也是并發(fā)執(zhí)行,因為階段 2 是與應(yīng)用線程并發(fā)執(zhí)行,可能有些引用關(guān)系已經(jīng)發(fā)生改變。

通過卡片標(biāo)記(Card Marking),提前把老年代空間邏輯劃分為相等大小的區(qū)域(Card)。

如果引用關(guān)系發(fā)生改變,JVM 會將發(fā)生改變的區(qū)域標(biāo)記為“臟區(qū)”(Dirty Card),然后在本階段,這些臟區(qū)會被找出來,刷新引用關(guān)系,清除“臟區(qū)”標(biāo)記。

階段 4:并發(fā)可取消的預(yù)清理(Concurrent Abortable Preclean)

此階段也不停止應(yīng)用線程。本階段嘗試在 STW 的最終標(biāo)記階段(Final Remark)之前盡可能地多做一些工作,以減少應(yīng)用暫停時間。

在該階段不斷循環(huán)處理:標(biāo)記老年代的可達(dá)對象、掃描處理 Dirty Card 區(qū)域中的對象,循環(huán)的終止條件有:

  • 達(dá)到循環(huán)次數(shù)
  • 達(dá)到循環(huán)執(zhí)行時間閾值
  • 新生代內(nèi)存使用率達(dá)到閾值

階段 5:最終標(biāo)記(Final Remark)

這是 GC 事件中第二次(也是最后一次)STW 階段,目標(biāo)是完成老年代中所有存活對象的標(biāo)記。

在此階段執(zhí)行:

  • 遍歷新生代對象,重新標(biāo)記
  • 根據(jù) GC Roots,重新標(biāo)記
  • 遍歷老年代的 Dirty Card,重新標(biāo)記

階段 6:并發(fā)清除(Concurrent Sweep)

 

此階段與應(yīng)用程序并發(fā)執(zhí)行,不需要 STW 停頓,根據(jù)標(biāo)記結(jié)果清除垃圾對象。

階段 7:并發(fā)重置(Concurrent Reset)

此階段與應(yīng)用程序并發(fā)執(zhí)行,重置 CMS 算法相關(guān)的內(nèi)部數(shù)據(jù), 為下一次 GC 循環(huán)做準(zhǔn)備。

CMS 常見問題

①最終標(biāo)記階段停頓時間過長問題

CMS 的 GC 停頓時間約 80% 都在最終標(biāo)記階段(Final Remark),若該階段停頓時間過長,常見原因是新生代對老年代的無效引用,在上一階段的并發(fā)可取消預(yù)清理階段中,執(zhí)行閾值時間內(nèi)未完成循環(huán),來不及觸發(fā) Young GC,清理這些無效引用。

通過添加參數(shù):-XX:+CMSScavengeBeforeRemark。

在執(zhí)行最終操作之前先觸發(fā) Young GC,從而減少新生代對老年代的無效引用,降低最終標(biāo)記階段的停頓。

但如果在上個階段(并發(fā)可取消的預(yù)清理)已觸發(fā) Young GC,也會重復(fù)觸發(fā) Young GC。

②并發(fā)模式失敗(concurrent mode failure)&晉升失敗(promotion failed)問題。

并發(fā)模式失敗:當(dāng) CMS 在執(zhí)行回收時,新生代發(fā)生垃圾回收,同時老年代又沒有足夠的空間容納晉升的對象時,CMS 垃圾回收就會退化成單線程的 Full GC。所有的應(yīng)用線程都會被暫停,老年代中所有的無效對象都被回收。

 

晉升失敗:當(dāng)新生代發(fā)生垃圾回收,老年代有足夠的空間可以容納晉升的對象,但是由于空閑空間的碎片化,導(dǎo)致晉升失敗,此時會觸發(fā)單線程且?guī)嚎s動作的 Full GC。

并發(fā)模式失敗和晉升失敗都會導(dǎo)致長時間的停頓,常見解決思路如下:

  • 降低觸發(fā) CMS GC 的閾值。
  • 即參數(shù) -XX:CMSInitiatingOccupancyFraction 的值,讓 CMS GC 盡早執(zhí)行,以保證有足夠的空間。
  • 增加 CMS 線程數(shù),即參數(shù) -XX:ConcGCThreads。
  • 增大老年代空間。
  • 讓對象盡量在新生代回收,避免進(jìn)入老年代。

③內(nèi)存碎片問題

通常 CMS 的 GC 過程基于標(biāo)記清除算法,不帶壓縮動作,導(dǎo)致越來越多的內(nèi)存碎片需要壓縮。

常見以下場景會觸發(fā)內(nèi)存碎片壓縮:

  • 新生代 Young GC 出現(xiàn)新生代晉升擔(dān)保失敗(promotion failed))
  • 程序主動執(zhí)行System.gc()

可通過參數(shù) CMSFullGCsBeforeCompaction 的值,設(shè)置多少次 Full GC 觸發(fā)一次壓縮。

默認(rèn)值為 0,代表每次進(jìn)入 Full GC 都會觸發(fā)壓縮,帶壓縮動作的算法為上面提到的單線程 Serial Old 算法,暫停時間(STW)時間非常長,需要盡可能減少壓縮時間。

G1 原理及調(diào)優(yōu)

G1 簡介

G1(Garbage-First)是一款面向服務(wù)器的垃圾收集器,支持新生代和老年代空間的垃圾收集,主要針對配備多核處理器及大容量內(nèi)存的機(jī)器。

G1 最主要的設(shè)計目標(biāo)是:實(shí)現(xiàn)可預(yù)期及可配置的 STW 停頓時間。

G1 堆空間劃分

 

①Region

為實(shí)現(xiàn)大內(nèi)存空間的低停頓時間的回收,將劃分為多個大小相等的 Region。每個小堆區(qū)都可能是 Eden 區(qū),Survivor 區(qū)或者 Old 區(qū),但是在同一時刻只能屬于某個代。

在邏輯上, 所有的 Eden 區(qū)和 Survivor 區(qū)合起來就是新生代,所有的 Old 區(qū)合起來就是老年代,且新生代和老年代各自的內(nèi)存 Region 區(qū)域由 G1 自動控制,不斷變動。

②巨型對象

當(dāng)對象大小超過 Region 的一半,則認(rèn)為是巨型對象(Humongous Object),直接被分配到老年代的巨型對象區(qū)(Humongous Regions)。

這些巨型區(qū)域是一個連續(xù)的區(qū)域集,每一個 Region 中最多有一個巨型對象,巨型對象可以占多個 Region。

G1 把堆內(nèi)存劃分成一個個 Region 的意義在于:

  • 每次 GC 不必都去處理整個堆空間,而是每次只處理一部分 Region,實(shí)現(xiàn)大容量內(nèi)存的 GC。
  • 通過計算每個 Region 的回收價值,包括回收所需時間、可回收空間,在有限時間內(nèi)盡可能回收更多的垃圾對象,把垃圾回收造成的停頓時間控制在預(yù)期配置的時間范圍內(nèi),這也是 G1 名稱的由來:Garbage-First。

G1工作模式

針對新生代和老年代,G1 提供 2 種 GC 模式,Young GC 和 Mixed GC,兩種會導(dǎo)致 Stop The World。

Young GC:當(dāng)新生代的空間不足時,G1 觸發(fā) Young GC 回收新生代空間。

Young GC 主要是對 Eden 區(qū)進(jìn)行 GC,它在 Eden 空間耗盡時觸發(fā),基于分代回收思想和復(fù)制算法,每次 Young GC 都會選定所有新生代的 Region。

同時計算下次 Young GC 所需的 Eden 區(qū)和 Survivor 區(qū)的空間,動態(tài)調(diào)整新生代所占 Region 個數(shù)來控制 Young GC 開銷。

Mixed GC:當(dāng)老年代空間達(dá)到閾值會觸發(fā) Mixed GC,選定所有新生代里的 Region,根據(jù)全局并發(fā)標(biāo)記階段(下面介紹到)統(tǒng)計得出收集收益高的若干老年代 Region。

在用戶指定的開銷目標(biāo)范圍內(nèi),盡可能選擇收益高的老年代 Region 進(jìn)行 GC,通過選擇哪些老年代 Region 和選擇多少 Region 來控制 Mixed GC 開銷。

全局并發(fā)標(biāo)記

 

全局并發(fā)標(biāo)記主要是為 Mixed GC 計算找出回收收益較高的 Region 區(qū)域,具體分為 5 個階段:

階段 1:初始標(biāo)記(Initial Mark)

暫停所有應(yīng)用線程(STW),并發(fā)地進(jìn)行標(biāo)記從 GC Root 開始直接可達(dá)的對象(原生棧對象、全局對象、JNI 對象)。

當(dāng)達(dá)到觸發(fā)條件時,G1 并不會立即發(fā)起并發(fā)標(biāo)記周期,而是等待下一次新生代收集,利用新生代收集的 STW 時間段,完成初始標(biāo)記,這種方式稱為借道(Piggybacking)。

階段 2:根區(qū)域掃描(Root Region Scan)

在初始標(biāo)記暫停結(jié)束后,新生代收集也完成的對象復(fù)制到 Survivor 的工作,應(yīng)用線程開始活躍起來。

此時為了保證標(biāo)記算法的正確性,所有新復(fù)制到 Survivor 分區(qū)的對象,需要找出哪些對象存在對老年代對象的引用,把這些對象標(biāo)記成根(Root)。

這個過程稱為根分區(qū)掃描(Root Region Scanning),同時掃描的 Suvivor 分區(qū)也被稱為根分區(qū)(Root Region)。

根分區(qū)掃描必須在下一次新生代垃圾收集啟動前完成(接下來并發(fā)標(biāo)記的過程中,可能會被若干次新生代垃圾收集打斷),因為每次 GC 會產(chǎn)生新的存活對象集合。

階段 3:并發(fā)標(biāo)記(Concurrent Marking)

標(biāo)記線程與應(yīng)用程序線程并行執(zhí)行,標(biāo)記各個堆中 Region 的存活對象信息,這個步驟可能被新的 Young GC 打斷。

所有的標(biāo)記任務(wù)必須在堆滿前就完成掃描,如果并發(fā)標(biāo)記耗時很長,那么有可能在并發(fā)標(biāo)記過程中,又經(jīng)歷了幾次新生代收集。

階段 4:再次標(biāo)記(Remark)

和 CMS 類似暫停所有應(yīng)用線程(STW),以完成標(biāo)記過程短暫地停止應(yīng)用線程, 標(biāo)記在并發(fā)標(biāo)記階段發(fā)生變化的對象,和所有未被標(biāo)記的存活對象,同時完成存活數(shù)據(jù)計算。

階段 5:清理(Cleanup)

為即將到來的轉(zhuǎn)移階段做準(zhǔn)備, 此階段也為下一次標(biāo)記執(zhí)行所有必需的整理計算工作:

  • 整理更新每個 Region 各自的 RSet(Remember Set,HashMap 結(jié)構(gòu),記錄有哪些老年代對象指向本 Region,key 為指向本 Region 的對象的引用,value 為指向本 Region 的具體 Card 區(qū)域,通過 RSet 可以確定 Region 中對象存活信息,避免全堆掃描)。
  • 回收不包含存活對象的 Region。
  • 統(tǒng)計計算回收收益高(基于釋放空間和暫停目標(biāo))的老年代分區(qū)集合。

G1調(diào)優(yōu)注意點(diǎn)

①Full GC 問題

G1 的正常處理流程中沒有 Full GC,只有在垃圾回收處理不過來(或者主動觸發(fā))時才會出現(xiàn),G1 的 Full GC 就是單線程執(zhí)行的 Serial old gc,會導(dǎo)致非常長的 STW,是調(diào)優(yōu)的重點(diǎn),需要盡量避免 Full GC。

常見原因如下:

  • 程序主動執(zhí)行 System.gc()
  • 全局并發(fā)標(biāo)記期間老年代空間被填滿(并發(fā)模式失敗)
  • Mixed GC 期間老年代空間被填滿(晉升失敗)
  • Young GC 時 Survivor 空間和老年代沒有足夠空間容納存活對象

類似 CMS,常見的解決是:

  • 增大 -XX:ConcGCThreads=n 選項增加并發(fā)標(biāo)記線程的數(shù)量,或者 STW 期間并行線程的數(shù)量:-XX:ParallelGCThreads=n。
  • 減小 -XX:InitiatingHeapOccupancyPercent 提前啟動標(biāo)記周期。
  • 增大預(yù)留內(nèi)存 -XX:G1ReservePercent=n,默認(rèn)值是 10,代表使用 10% 的堆內(nèi)存為預(yù)留內(nèi)存,當(dāng) Survivor 區(qū)域沒有足夠空間容納新晉升對象時會嘗試使用預(yù)留內(nèi)存。

②巨型對象分配

巨型對象區(qū)中的每個 Region 中包含一個巨型對象,剩余空間不再利用,導(dǎo)致空間碎片化,當(dāng) G1 沒有合適空間分配巨型對象時,G1 會啟動串行 Full GC 來釋放空間。

可以通過增加 -XX:G1HeapRegionSize 來增大 Region 大小,這樣一來,相當(dāng)一部分的巨型對象就不再是巨型對象了,而是采用普通的分配方式。

③不要設(shè)置 Young 區(qū)的大小

原因是為了盡量滿足目標(biāo)停頓時間,邏輯上的 Young 區(qū)會進(jìn)行動態(tài)調(diào)整。如果設(shè)置了大小,則會覆蓋掉并且會禁用掉對停頓時間的控制。

④平均響應(yīng)時間設(shè)置

使用應(yīng)用的平均響應(yīng)時間作為參考來設(shè)置 MaxGCPauseMillis,JVM 會盡量去滿足該條件,可能是 90% 的請求或者更多的響應(yīng)時間在這之內(nèi), 但是并不代表是所有的請求都能滿足,平均響應(yīng)時間設(shè)置過小會導(dǎo)致頻繁 GC。

調(diào)優(yōu)方法與思路

如何分析系統(tǒng) JVM GC 運(yùn)行狀況及合理優(yōu)化?

GC 優(yōu)化的核心思路在于:盡可能讓對象在新生代中分配和回收,盡量避免過多對象進(jìn)入老年代,導(dǎo)致對老年代頻繁進(jìn)行垃圾回收,同時給系統(tǒng)足夠的內(nèi)存減少新生代垃圾回收次數(shù),進(jìn)行系統(tǒng)分析和優(yōu)化也是圍繞著這個思路展開。

分析系統(tǒng)的運(yùn)行狀況

分析系統(tǒng)的運(yùn)行狀況:

  • 系統(tǒng)每秒請求數(shù)、每個請求創(chuàng)建多少對象,占用多少內(nèi)存。
  • Young GC 觸發(fā)頻率、對象進(jìn)入老年代的速率。
  • 老年代占用內(nèi)存、Full GC 觸發(fā)頻率、Full GC 觸發(fā)的原因、長時間 Full GC 的原因。

常用工具如下:

jstat:JVM 自帶命令行工具,可用于統(tǒng)計內(nèi)存分配速率、GC 次數(shù),GC 耗時。

常用命令格式:

  1. jstat -gc <pid> <統(tǒng)計間隔時間>  <統(tǒng)計次數(shù)> 

輸出返回值代表含義如下:

 

例如:jstat -gc 32683 1000 10,統(tǒng)計 pid=32683 的進(jìn)程,每秒統(tǒng)計 1 次,統(tǒng)計 10 次。

jmap:JVM 自帶命令行工具,可用于了解系統(tǒng)運(yùn)行時的對象分布。

常用命令格式如下:

  1. // 命令行輸出類名、類數(shù)量數(shù)量,類占用內(nèi)存大小, 
  2. // 按照類占用內(nèi)存大小降序排列 
  3. jmap -histo <pid> 
  4.  
  5. // 生成堆內(nèi)存轉(zhuǎn)儲快照,在當(dāng)前目錄下導(dǎo)出dump.hrpof的二進(jìn)制文件, 
  6. // 可以用eclipse的MAT圖形化工具分析 
  7. jmap -dump:live,format=b,file=dump.hprof <pid> 

jinfo,命令格式: 

  1. jinfo <pid>  

用來查看正在運(yùn)行的 Java 應(yīng)用程序的擴(kuò)展參數(shù),包括 Java System 屬性和 JVM 命令行參數(shù)。

其他 GC 工具:

  • 監(jiān)控告警系統(tǒng):Zabbix、Prometheus、Open-Falcon
  • jdk 自動實(shí)時內(nèi)存監(jiān)控工具:VisualVM
  • 堆外內(nèi)存監(jiān)控:Java VisualVM 安裝 Buffer Pools 插件、google perf工具、Java NMT(Native Memory Tracking)工具
  • GC 日志分析:GCViewer、gceasy
  • GC 參數(shù)檢查和優(yōu)化:http://xxfox.perfma.com/

GC 優(yōu)化案例

①數(shù)據(jù)分析平臺系統(tǒng)頻繁 Full GC

平臺主要對用戶在 App 中行為進(jìn)行定時分析統(tǒng)計,并支持報表導(dǎo)出,使用 CMS GC 算法。

數(shù)據(jù)分析師在使用中發(fā)現(xiàn)系統(tǒng)頁面打開經(jīng)常卡頓,通過 jstat 命令發(fā)現(xiàn)系統(tǒng)每次 Young GC 后大約有 10% 的存活對象進(jìn)入老年代。

原來是因為 Survivor 區(qū)空間設(shè)置過小,每次 Young GC 后存活對象在 Survivor 區(qū)域放不下,提前進(jìn)入老年代。

通過調(diào)大 Survivor 區(qū),使得 Survivor 區(qū)可以容納 Young GC 后存活對象,對象在 Survivor 區(qū)經(jīng)歷多次 Young GC 達(dá)到年齡閾值才進(jìn)入老年代。

調(diào)整之后每次 Young GC 后進(jìn)入老年代的存活對象穩(wěn)定運(yùn)行時僅幾百 Kb,F(xiàn)ull GC 頻率大大降低。

②業(yè)務(wù)對接網(wǎng)關(guān) OOM

網(wǎng)關(guān)主要消費(fèi) Kafka 數(shù)據(jù),進(jìn)行數(shù)據(jù)處理計算然后轉(zhuǎn)發(fā)到另外的 Kafka 隊列,系統(tǒng)運(yùn)行幾個小時候出現(xiàn) OOM,重啟系統(tǒng)幾個小時之后又 OOM。

通過 jmap 導(dǎo)出堆內(nèi)存,在 eclipse MAT 工具分析才找出原因:代碼中將某個業(yè)務(wù) Kafka 的 topic 數(shù)據(jù)進(jìn)行日志異步打印,該業(yè)務(wù)數(shù)據(jù)量較大,大量對象堆積在內(nèi)存中等待被打印,導(dǎo)致 OOM。

③賬號權(quán)限管理系統(tǒng)頻繁長時間 Full GC

系統(tǒng)對外提供各種賬號鑒權(quán)服務(wù),使用時發(fā)現(xiàn)系統(tǒng)經(jīng)常服務(wù)不可用,通過 Zabbix 的監(jiān)控平臺監(jiān)控發(fā)現(xiàn)系統(tǒng)頻繁發(fā)生長時間 Full GC,且觸發(fā)時老年代的堆內(nèi)存通常并沒有占滿,發(fā)現(xiàn)原來是業(yè)務(wù)代碼中調(diào)用了 System.gc()。

總結(jié)

GC 問題可以說沒有捷徑,排查線上的性能問題本身就并不簡單,除了將本文介紹到的原理和工具融會貫通,還需要我們不斷去積累經(jīng)驗,真正做到性能最優(yōu)。

篇幅所限,不再展開介紹常見 GC 參數(shù)的使用,我發(fā)布在 GitHub:

  1. https://github.com/caison/caison-blog-demo 

參考:

  • 《Java Performance: The Definitive Guide》 Scott Oaks
  • 《深入理解 Java 虛擬機(jī):JVM 高級特性與最佳實(shí)踐(第二版》 周志華
  • Java 性能調(diào)優(yōu)實(shí)戰(zhàn)
  • Getting Started with the G1 Garbage Collector
  • GC 參考手冊-Java 版
  • 請教 G1 算法的原理——RednaxelaFX 的回答
  • Java Hotspot G1 GC 的一些關(guān)鍵技術(shù)——美團(tuán)技術(shù)團(tuán)隊

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2019-02-21 16:24:28

5G火車站設(shè)備

2020-03-02 15:17:37

云原生CNCF容器

2021-02-25 08:21:38

高可用風(fēng)險故障

2019-07-04 09:13:04

中臺百度團(tuán)隊

2020-10-29 10:35:53

Nginx架構(gòu)服務(wù)器

2018-03-06 10:32:51

程序員代碼開發(fā)

2022-11-11 15:49:41

MySQL隔離

2019-10-21 08:51:41

分布式事務(wù)CAPAP

2018-07-26 09:06:29

Java內(nèi)存模型

2015-06-29 14:39:29

2020-01-13 15:34:10

超融合邊緣計算架構(gòu)

2021-02-11 08:08:09

Spring Boot配置架構(gòu)

2019-11-23 17:27:54

IO開源

2010-08-05 14:44:29

數(shù)據(jù)中心停機(jī)成本

2015-02-26 10:52:07

2025-06-23 08:20:00

PaimonFluss大數(shù)據(jù)

2016-11-08 13:34:44

大數(shù)據(jù)契機(jī)貸后

2024-09-23 05:10:00

微服務(wù)CORSSpringBoot

2017-11-06 18:32:23

iOS

2021-04-01 22:26:18

人工智能消費(fèi)者權(quán)益線上信貸
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

亚洲在线观看一区| 成人午夜在线影院| 纪美影视在线观看电视版使用方法| 亚洲wwww| 一区二区三区视频在线看| 国产精品一区二| 羞羞色院91蜜桃| 亚洲视频中文| 在线观看国产欧美| 亚洲成年人av| 国产激情欧美| 欧美日韩亚洲精品一区二区三区| 亚洲免费在线精品一区| 人妻一区二区三区| 精品一区在线看| 欧美影院久久久| www.5588.com毛片| 欧美色图国产精品| 亚洲国产精品电影在线观看| 蜜桃福利午夜精品一区| 日韩电影免费观| 亚洲福利视频一区| 激情视频小说图片| 色哟哟免费在线观看| 大桥未久av一区二区三区中文| 国产精品久久久精品| 日本中文字幕在线| 在线成人黄色| 欧美国产极速在线| 黄色录像免费观看| 成人影院在线| 亚洲一区二区国产| jizz日本免费| 9l亚洲国产成人精品一区二三| 欧美精品一二三区| 精品少妇无遮挡毛片| 神马久久午夜| 天天综合网天天综合色| 男人添女荫道口喷水视频| 黄视频网站在线| 国产精品国产三级国产普通话三级 | 97se国产在线视频| 这里只有久久精品视频| 久久经典综合| 全亚洲最色的网站在线观看| 国产特黄大片aaaa毛片| 亚洲二区精品| 韩国精品久久久999| 黄色小说在线观看视频| 黄色在线成人| 国内外成人免费激情在线视频| 久草国产在线视频| 欧美激情aⅴ一区二区三区| 超薄丝袜一区二区| 黄色一级片中国| 午夜国产精品视频免费体验区| 久久国产精品久久久久| 欧美成人三级视频| 狠狠久久婷婷| 97国产一区二区精品久久呦| 精品欧美一区二区三区免费观看| 一道本一区二区| 日本久久中文字幕| 波多野结衣二区三区| 免费日本视频一区| 91丨九色丨国产在线| 国产绿帽刺激高潮对白| 国产盗摄一区二区三区| 国产富婆一区二区三区 | 亚洲精品一区二区在线| 麻豆精品免费视频| 91欧美大片| 欧美激情久久久久久| 国产三级av片| 日韩av在线播放中文字幕| 成人黄在线观看| 黄色片网站免费在线观看| 91在线观看地址| 日本一区免费| 1区2区3区在线视频| 亚洲午夜一区二区| caopor在线视频| 激情五月综合婷婷| 亚洲丁香久久久| av免费播放网站| 欧美成人有码| 奇米一区二区三区四区久久| 亚洲天堂自拍偷拍| 成人性色生活片| 日韩精品极品视频在线观看免费| 国产黄色在线免费观看| 精品久久久久久中文字幕一区奶水 | 成人午夜在线影视| 天天av天天翘天天综合网色鬼国产| 99热手机在线| 日韩区一区二| 国产亚洲精品美女久久久久| 久久99久久98精品免观看软件| 先锋影音久久| 成人欧美一区二区三区在线观看 | 久久久久国产精品厨房| 中文字幕99| av资源亚洲| 欧美一区2区视频在线观看| 国产偷人妻精品一区| 久久久久国产| 国产精品成人av性教育| 国产 日韩 欧美 精品| 中文字幕二三区不卡| 无码粉嫩虎白一线天在线观看| 日本.亚洲电影| 亚洲国产高清高潮精品美女| 一本一本久久a久久| 午夜一级久久| 黄色一区三区| 日韩特级毛片| 欧美一区二区在线视频| 久久视频一区二区三区| 国产精品腿扒开做爽爽爽挤奶网站| 92看片淫黄大片看国产片| 国产毛片av在线| 欧美日韩激情美女| 欧美人与性动交α欧美精品| 色狮一区二区三区四区视频| 日韩美女在线观看| 四虎精品在线| 亚洲在线一区二区三区| 北条麻妃亚洲一区| 91久久高清国语自产拍| 国产精品久久久久免费a∨大胸| 日本精品久久久久久| 一区二区三区久久久| 天天看片天天操| 国产精品99在线观看| 国产精品高潮在线| 成人激情电影在线看| 色综合久久久久网| 成人片黄网站色大片免费毛片| 国产亚洲网站| 久久久久久九九| 午夜欧美激情| 日韩精品在线视频观看| 国产高清中文字幕| 久久一区二区视频| 可以免费观看av毛片| 精品国产一区二区三区久久久蜜臀 | 国产91精品精华液一区二区三区| 无码人妻精品一区二区三区99v| 欧美亚洲黄色| 欧美成人合集magnet| 国内精品久久久久久久久久久| 亚洲婷婷综合色高清在线| 午夜av中文字幕| 午夜精品久久| 极品尤物一区二区三区| 九色porny自拍视频在线观看| 亚洲成人免费在线视频| 69成人免费视频| 日本一区二区免费在线| 中文字幕丰满乱码| 欧美日韩精品| 国产私拍一区| 超碰一区二区| 国产一区二区三区视频| 国产一区二区在线视频观看| 亚洲精品中文在线影院| 国产精品入口麻豆| 午夜在线精品| 一区二区三区欧美在线| 亚洲精品一区二区三区中文字幕| 欧美激情视频三区| 天堂a中文在线| 欧美性一二三区| 日韩在线观看视频一区二区| 不卡一卡二卡三乱码免费网站| 日韩毛片在线免费看| 久久蜜桃av| 99视频免费观看| 伊伊综合在线| 欧美成人中文字幕| 日本一卡二卡四卡精品| 欧美日韩aaa| 久草精品视频在线观看| 欧美韩日一区二区三区四区| 中文字幕一二三| 日韩电影在线观看网站| 波多野结衣与黑人| 欧美理论电影大全| 91久久久一线二线三线品牌| 最新欧美色图| 美女精品视频一区| 免费在线性爱视频| 欧美一级久久久| 精品人妻一区二区三区免费看| 国产精品久久久久一区二区三区共| 国产调教打屁股xxxx网站| 日韩精品成人一区二区在线| av一区二区三区免费观看| 精品久久不卡| 国产精品一区免费观看| 久久天天久久| 欧美一区二三区| 影音先锋在线视频| 永久免费看mv网站入口亚洲| 男人天堂手机在线观看| 欧美色电影在线| 免费看毛片网站| 一二三区精品福利视频| 日韩亚洲欧美中文字幕| 久久久影视传媒| 年下总裁被打光屁股sp| 国内精品国产成人| 超碰在线97免费| 久久激情综合| 亚洲 高清 成人 动漫| 午夜欧美视频| 日本不卡一区二区三区四区| 精品盗摄女厕tp美女嘘嘘| 国产精品一区二区三区不卡| 欧美专区一区| 成人美女av在线直播| 91福利精品在线观看| 欧美亚洲国产精品| 日本免费一区二区六区| 久久免费视频网| 男女羞羞视频在线观看| 欧美人在线视频| 污污的视频在线观看| 久久夜精品香蕉| 香蕉视频免费在线播放| 中文字幕少妇一区二区三区| 国产福利在线看| 亚洲丝袜一区在线| 日韩专区一区二区| 日韩精品中文字幕视频在线| 黄色小视频免费在线观看| 日韩美女在线视频| 性做久久久久久久久久| 日韩一区二区在线观看| 国产成人免费看一级大黄| 91精品国模一区二区三区| 国产精品热久久| 欧美精品视频www在线观看| 一级黄色片视频| 在线不卡欧美精品一区二区三区| 中文字幕在线视频免费| 欧美日韩精品一区二区在线播放 | 日韩欧美国产综合一区| 性生活视频软件| 欧美电影精品一区二区| 欧美在线精品一区二区三区| 亚洲国产欧美一区| 日韩精品视频无播放器在线看| 亚洲欧美国产日韩天堂区| 国产小视频在线| 中文字幕亚洲综合久久筱田步美| 男人影院在线观看| 久久福利视频网| av在线网页| 国产mv久久久| 亚洲精品三区| 成人欧美一区二区三区视频 | 国产在线精品一区二区不卡了| 九九九九九九九九| 高清日韩电视剧大全免费| 精品一区二区视频在线观看| 久久久五月婷婷| 美女三级黄色片| 亚洲国产成人av网| 久草视频一区二区| 欧美三级午夜理伦三级中视频| 一本色道久久综合无码人妻| 91精品国产一区二区三区| 亚洲欧美黄色片| 亚洲欧洲午夜一线一品| 日本三级在线播放完整版| 欧美精品在线看| 精品人人视频| 国产精品一区二区在线| 亚洲一区网址| 欧美亚洲免费高清在线观看| 91欧美在线| 日韩伦理在线免费观看| 丝袜美腿成人在线| 伦伦影院午夜理论片| 久久婷婷一区二区三区| 国产午夜精品理论片| 污片在线观看一区二区| 亚洲综合精品国产一区二区三区| 日韩精品一区二区三区中文精品 | 成人午夜三级| 婷婷四房综合激情五月| 尤物网精品视频| 玖玖爱视频在线| 91视频在线观看免费| 日本午夜在线观看| 色哟哟一区二区在线观看| 国产福利小视频| 在线视频欧美日韩| 国产自产自拍视频在线观看| 成人av资源在线播放| 亚洲制服欧美另类| 女人被男人躁得好爽免费视频| 麻豆91在线看| 37p粉嫩大胆色噜噜噜| 一区二区激情视频| 在线观看xxxx| 亚洲欧美精品一区| h片视频在线观看| 96sao精品视频在线观看| 国产欧美日韩精品一区二区免费| 国产一区 在线播放| 久久超碰97中文字幕| 免费看污片网站| 欧美日韩精品在线| 人妻无码中文字幕| 欧美激情第一页xxx| 精品一区二区三区亚洲| 亚洲va韩国va欧美va精四季| 国产精品永久| 久久精品女同亚洲女同13| 一卡二卡三卡日韩欧美| 国产手机视频在线| 按摩亚洲人久久| 久久夜夜久久| 天堂va久久久噜噜噜久久va| 久久一二三四| 精品人妻互换一区二区三区| 精品免费在线观看| 色一情一乱一乱一区91av| 久久久亚洲精选| 91精品啪在线观看国产手机| 久久久久久久久影视| 精品午夜久久福利影院| 精品少妇一区二区三区密爱| 欧美日韩一级大片网址| 三区四区电影在线观看| 国产欧美在线观看| 97国产成人高清在线观看| 91女神在线观看| 中文字幕一区二区日韩精品绯色| 中文字幕 日韩有码| 揄拍成人国产精品视频| 国产精品毛片久久久久久久久久99999999 | 精品人妻少妇嫩草av无码专区| 最新69国产成人精品视频免费| 成人在线免费av| 亚洲国产精品影视| 国产精品一区二区x88av| 久久久国产精品人人片| 精品国产乱码久久久久久老虎| 大香伊人中文字幕精品| 国产在线一区二区三区播放| 国产农村妇女精品一二区| 一级黄色片大全| 欧美日韩国产经典色站一区二区三区| 日本a级在线| 亚洲xxx自由成熟| 亚洲黑丝一区二区| 在线观看日本中文字幕| 欧美日高清视频| 激情网站在线| 蜜桃在线一区二区三区精品| 日韩成人av影视| caoporn91| 日韩av网站电影| 久久爱.com| 天堂8在线天堂资源bt| 久久亚区不卡日本| 亚洲一级黄色大片| 欧美精品久久久久久久久久| 男男gay无套免费视频欧美| www.久久91| 图片区小说区区亚洲影院| 成人h小游戏| 岛国视频一区| 日韩综合一区二区| 国产一区二区播放| 亚洲精品一区二区网址| 亚洲欧洲二区| 无码播放一区二区三区| 中文字幕一区二区三区蜜月| 后进极品白嫩翘臀在线视频| 日韩av电影手机在线| 欧美91精品| 一级片视频免费看| 日韩精品最新网址| 成人免费网站www网站高清| 国产日韩欧美大片| 91老师片黄在线观看| 国产绿帽一区二区三区| 日韩免费观看av| 欧美激情四色| av手机在线播放| 精品99久久久久久| 日韩久久99| 狠狠爱免费视频| 亚洲自拍与偷拍| 免费网站成人| 欧美视频1区|