久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

HotSpot 垃圾回收算法實現(xiàn) | 碼蜂筆記

 hh3755 2014-07-25

《深入理解Java虛擬機(jī):JVM高級特性與最佳實踐》-筆記

垃圾回收算法

枚舉根結(jié)點

一致性

在可達(dá)性分析期間整個系統(tǒng)看起來就像被凍結(jié)在某個時間點上,不可以出現(xiàn)分析過程中對象引用關(guān)系還在不斷變化的情況,。

一致性要求導(dǎo)致GC進(jìn)行時必須停頓所有Java執(zhí)行線程,。(Stop The World)
即使在號稱不會發(fā)生停頓的CMS收集器中,枚舉根節(jié)點時也是必須停頓的,。

HotSpot使用的是準(zhǔn)確式GC,,當(dāng)執(zhí)行系統(tǒng)停頓下來后,并不需要一個不漏地檢查完所有執(zhí)行上下文和全局的引用位置,,這是通過一組稱為OopMap的數(shù)據(jù)結(jié)構(gòu)來達(dá)到的,。

在類加載完成后,HotSpot就把對象內(nèi)什么偏移量上是什么類型的數(shù)據(jù)計算出來,;在JIT編譯過程中,,也會在特定的位置記錄下棧和寄存器中哪些位置是引用。

安全點(Safe Point)

程序只有在到達(dá)安全點時才能暫停,。安全點的選定標(biāo)準(zhǔn)是“是否具有讓程序長時間執(zhí)行的特征”,。“長時間執(zhí)行”的最明顯特征就是指令序列的復(fù)用,,如方法調(diào)用,、循環(huán)跳轉(zhuǎn)等,具有這些功能的指令才會產(chǎn)生安全點,。

讓程序暫停的兩種方式

  • 搶先式中斷(Preemptive Suspension):在GC發(fā)生時,,主動中斷所有線程,不需要線程執(zhí)行的代碼主動配合,。幾乎不被采用,。

  • 主動式中斷(Voluntary Suspension):設(shè)一個標(biāo)志,,各個線程主動去輪詢這個標(biāo)志,遇到中斷則暫停,。輪詢地方與安全點重合,。

安全區(qū)域(Safe Region)

指在一段代碼片段中,引用關(guān)系不會發(fā)生變化,。在這個區(qū)域的任意地方開始GC都是安全的,。

線程執(zhí)行到安全區(qū)域中的代碼時,首先標(biāo)識自己進(jìn)入了安全區(qū)域,;在離開安全區(qū)域時,,要檢查系統(tǒng)是否已經(jīng)完成了枚舉根節(jié)點(或整個GC過程),完成了就繼續(xù)執(zhí)行,,否則必須等待直到收到可以安全離開Safe Region的信號,。

安全區(qū)域是為了解決線程Sleep或Blocked狀態(tài)的。

垃圾收集器

前面的垃圾收集算法是理論,,垃圾收集器則是具體的實現(xiàn),。

下圖是HotSpot里的收集器,中間的橫線表示分代,,有連線表示可以組合使用,。

Serial 收集器

是一個單線程的收集器,只能使用一個CPU或一條線程去完成垃圾收集,;在進(jìn)行垃圾收集時,,必須暫停所有其他工作線程,直到收集完成,。

Serial/Serial Old 收集器運行示意圖:
Serial_gc_runtime

缺點:Stop-The-World,。

優(yōu)勢:簡單。對于但CPU的情況,,由于沒有多線程交互開銷,,反而可以更高效。

是Client模式下默認(rèn)的新生代收集器,。

ParNew 收集器

是Serial收集器的多線程版本。

ParNew/Serial Old 收集器運行示意圖:
ParNew_gc_runtime

垃圾收集語境下的并發(fā)與并行概念

  • 并行(Parallel):指多條垃圾收集線程并行工作,,用戶線程仍然處于等待狀態(tài),。
  • 并發(fā)(Concurrent):用戶線程與垃圾收集線程同時執(zhí)行。

Parallel Scavenge 收集器

新生代收集器,,使用復(fù)制算法,、并行的多線程收集器。

Parallel Scavenge 收集器的目標(biāo)是達(dá)到一個可控制的吞吐量(Throughput),。這里的吞吐量是指CPU用于運行用戶代碼的時間與CPU總消耗時間的比值,。主要適合在后臺運算而不需要太多交互的任務(wù),。

Parallel Scavenge 收集器允許采用GC自適應(yīng)的調(diào)節(jié)策略,也就是讓虛擬機(jī)根據(jù)收集到的運行時數(shù)據(jù)自行決定各個分代的大小等與垃圾回收有關(guān)的配置,。

Serial Old 收集器

用于老年代的Serial收集器,,單線程,使用“標(biāo)記-整理”算法,。

SerialOld_gc_runtime

主要在Client模式下使用,。

Parallel Old 收集器

Parallel Scavenge的老年代版本,多線程,,使用“標(biāo)記-整理”算法,。

ParallelOld_gc_runtime

CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標(biāo)的收集器?;凇皹?biāo)記-清除”算法,。

CMS_gc_runtime

運作過程分為4個階段:

  • 初始標(biāo)記(CMS initial mark):值標(biāo)記GC Roots能直接關(guān)聯(lián)到的對象。
  • 并發(fā)標(biāo)記(CMS concurrent mark):進(jìn)行GC RootsTracing的過程,。
  • 重新標(biāo)記(CMS remark):修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運行而導(dǎo)致標(biāo)記發(fā)生改變的那一部分對象的標(biāo)記,。
  • 并發(fā)清除(CMS concurrent sweep):

其中標(biāo)記和重新標(biāo)記兩個階段仍然需要Stop-The-World,整個過程中耗時最長的并發(fā)標(biāo)記和并發(fā)清除過程中收集器都可以和用戶線程一起工作,。

CMS收集器對CPU資源非常敏感,。

浮動垃圾(Floating Garbage):由于CMS并發(fā)清理階段用戶線程還在運行著,自然會有新的垃圾產(chǎn)生,,而這些垃圾是在標(biāo)記過程之后,,CMS只能在下次GC時回收它們,這些垃圾就稱為浮動垃圾,。

CMS收集器無法處理浮動垃圾,,可能出現(xiàn)“Concurrent Mode Failure”失敗而導(dǎo)致另一次Full GC的產(chǎn)生。

在垃圾收集階段用戶線程還在運行,,因此需要預(yù)留足夠的內(nèi)存給用戶線程使用,。如果預(yù)留內(nèi)存不能滿足用戶線程,會出現(xiàn)“Concurrent Mode Failure”,,這時虛擬機(jī)將啟動臨時后備預(yù)案:臨時啟用Serial Old收集器來重新進(jìn)行老年代的垃圾收集,。

由于CMS使用的是清除算法,會導(dǎo)致內(nèi)存碎片問題,,因此提供了參數(shù)用于控制是否在進(jìn)行FullGC后進(jìn)行內(nèi)存整理,,還提供了參數(shù)用于控制在多少次FullGC時才進(jìn)行內(nèi)存整理。內(nèi)存整理是不能并發(fā)的,,也就是要暫停所有用戶線程,。

G1 收集器

G1(Garbage First):是一款面向服務(wù)端應(yīng)用的垃圾收集器,用于替換CMS收集器,。

G1_gc_runtime

G1將整個Java堆劃分為大小相等的獨立區(qū)域(Region),;新生代和老年代不再是物理隔離的,,都由一組不連續(xù)的Region組成。

G1的特點:

  • 并行與并發(fā):充分利用多CPU縮短Stop-The-World停頓時間,,在收集過程中用并發(fā)的方式讓Java線程繼續(xù)執(zhí)行,。
  • 分代收集:仍然有分代的概念,不需要其他收集器配合,,獨立管理整個GC堆,。
  • 空間整合:從整體看,是基于“標(biāo)記-整理”算法實現(xiàn)的,,從局部(兩個Region之間)看是基于“復(fù)制”算法的,。在運行期間不會產(chǎn)生內(nèi)存碎片。
  • 可預(yù)測的停頓:G1跟蹤各個Region里垃圾堆積值的價值大小,,維護(hù)一個優(yōu)先級隊列,,每次根據(jù)允許的時間,優(yōu)先回收價值最大的Region,。(這也是Garbage First的由來)

Region之間的對象引用以及其他收集器中的新生代與老年代之間的對象引用,,虛擬機(jī)都是使用Remembered Set來避免全堆掃描的。

G1中每個Region都有一個與之對應(yīng)的Remembered Set,,虛擬機(jī)發(fā)現(xiàn)程序?qū)σ妙愋偷臄?shù)據(jù)進(jìn)行寫操作時,,會產(chǎn)生一個Write Barrier暫時中斷寫操作,檢查引用的對象是否處于不同的Region中(在其他收集器中就是檢查是否老年代中的對象引用了新生代中對象),,如果是,,通過CardTable把相關(guān)引用信息記錄到被引用對象所屬的Region的Remembered Set中。進(jìn)行內(nèi)存回收時,,在GC根節(jié)點的枚舉范圍中加入Remembered Set即可保證不對全堆掃描也不會有遺漏,。

G1垃圾回收主要有4個階段:

  • 初始標(biāo)記:只標(biāo)記GC Roots能直接關(guān)聯(lián)到的對象,并且修改TAMS(Next Top at Mark Start)值,,讓下一階段用戶程序并發(fā)運行時,,能在正確可用的Region中創(chuàng)建新對象。此階段需要暫停用戶線程,。
  • 并發(fā)標(biāo)記:從GC Roots開始對堆中對象進(jìn)行可達(dá)性分析,,找出存活對象;耗時較長,,可與用戶線程并發(fā)執(zhí)行,。
  • 最終標(biāo)記:修正在并發(fā)標(biāo)記期間有變動的標(biāo)記記錄。
  • 刷選回收:對各個Region的回收價值和成本進(jìn)行排序,,根據(jù)用戶期望的GC停頓時間制定回收計劃,進(jìn)行垃圾回收,。

內(nèi)存分配與回收規(guī)則

內(nèi)存分配與回收規(guī)則由垃圾回收器和內(nèi)存有關(guān)參數(shù)決定,,不是固定的,。

兩個概念:

  • MinorGC,次收集:在新生代發(fā)生的垃圾收集,,速度快,,發(fā)生頻繁。
  • FullGC,,MajorGC,,主收集:發(fā)生在年老代的垃圾收集。一般伴隨一次MinorGC,。

一般的規(guī)則:

  • 對象優(yōu)先在Eden分配,。當(dāng)Eden沒有足夠的空間時,虛擬機(jī)將發(fā)起一次MinorGC,。

  • 大對象直接進(jìn)入老年代,。大對象是指需要連續(xù)內(nèi)存空間的Java對象。目的是避免在Eden區(qū)及兩個Survivor區(qū)之間大量的內(nèi)存復(fù)制(新生代采用復(fù)制算法收集內(nèi)存),。

  • 長期存活對象將進(jìn)入老年代,。虛擬機(jī)給每個對象定義一個對象年齡計數(shù)器,如果對象在Eden出生并經(jīng)過一次Minor GC后仍然存活,,并且能夠被Survivor容納,,將被移動到Survivor空間,并且對象年齡設(shè)為1,。對象在Survivor區(qū)中每“熬過”一次MinorGC,,年齡就加1,達(dá)到某個閥值就晉升到年老代,。

  • 空間分配擔(dān)保,。在發(fā)生Minor GC之前,虛擬機(jī)會先檢查年老代最大可用的連續(xù)空間算法大于新生代所有對象總空間,,如果是,,那么Minor GC可以確保是安全的。如果否,,虛擬機(jī)會查看HandlePromotionFailure設(shè)置是否允許擔(dān)保失敗,。如果允許繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于,,將嘗試進(jìn)行一次Minor GC,,這是有風(fēng)險的(存活對象占用的內(nèi)存大于平均大小,將導(dǎo)致HandlePromotionFailure失敗,,重新發(fā)起一次Full GC),;如果小于或者HandlePromotionFailure設(shè)置不允許冒險,將改為Full GC。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多