From:深入理解Java虛擬機(jī)
- 目錄
BiBi - JVM -0- 開(kāi)篇
BiBi - JVM -1- Java內(nèi)存區(qū)域
BiBi - JVM -2- 對(duì)象
BiBi - JVM -3- 垃圾收集算法
BiBi - JVM -4- HotSpot JVM
BiBi - JVM -5- 垃圾回收器
BiBi - JVM -6- 回收策略
BiBi - JVM -7- Java類(lèi)文件結(jié)構(gòu)
BiBi - JVM -8- 類(lèi)加載機(jī)制
BiBi - JVM -9- 類(lèi)加載器
BiBi - JVM -10- 虛擬機(jī)字節(jié)碼
BiBi - JVM -11- 編譯期優(yōu)化
BiBi - JVM -12- 運(yùn)行期優(yōu)化
BiBi - JVM -13- 并發(fā)
問(wèn)題1:GC Roots節(jié)點(diǎn)尋找引用鏈耗時(shí),并且該分析要保證一致性,即不會(huì)出現(xiàn)分析過(guò)程中對(duì)象引用關(guān)系還在不斷變化的情況船殉,該如何?
GC進(jìn)行時(shí)必須停頓所有Java線(xiàn)程 — Stop The World咽斧。
GC Roots節(jié)點(diǎn)主要在全局性的引用【常量或類(lèi)靜態(tài)屬性】和執(zhí)行上下文【棧楨中的本地變量表】中。但躬存,并不需要一個(gè)不漏地檢查完所有全局的引用和執(zhí)行上下文张惹,HotSpot使用OopMap的數(shù)據(jù)結(jié)構(gòu),在類(lèi)加載完成的時(shí)候岭洲,HotSpot就把對(duì)象內(nèi)什么偏移量上是什么類(lèi)型的數(shù)據(jù)都計(jì)算出來(lái)宛逗,在JIT編譯過(guò)程中,也會(huì)在特定的位置記錄棧和寄存器中哪些位置是引用盾剩。所以通過(guò)OopMap雷激,GC在掃描時(shí)就可以直接得知這些信息替蔬。
問(wèn)題2:在OopMap的協(xié)助下,HotSpot可以快速且準(zhǔn)確的完成GC Roots枚舉屎暇,但如果為每一條指令都生成對(duì)應(yīng)的OopMap承桥,GC的空間成本將會(huì)很高?
要在特定的位置記錄這些信息根悼,這些位置稱(chēng)為【安全點(diǎn)凶异,Safepoint】,即程序執(zhí)行時(shí)并非在所有地方都停頓下來(lái)開(kāi)始GC挤巡,只有在到達(dá)安全點(diǎn)時(shí)才可以剩彬。具有產(chǎn)生安全點(diǎn)指令的功能有:方法調(diào)用、循環(huán)跳轉(zhuǎn)矿卑、異常跳轉(zhuǎn)等喉恋。
安全點(diǎn)的選定既不能太少以致于讓GC執(zhí)行時(shí)間太長(zhǎng);也不能過(guò)于頻繁以致于增大運(yùn)行負(fù)荷母廷。
問(wèn)題3:GC發(fā)生時(shí)轻黑,如何讓所有【不包括JNI線(xiàn)程】線(xiàn)程都“跑”到最近的安全點(diǎn)上再停頓下來(lái)?
采用【主動(dòng)式中斷】的思想:當(dāng)GC需要中斷線(xiàn)程時(shí)琴昆,不直接對(duì)線(xiàn)程操作苔悦,而是簡(jiǎn)單的設(shè)置一個(gè)標(biāo)志,各個(gè)線(xiàn)程執(zhí)行時(shí)主動(dòng)去輪詢(xún)這個(gè)標(biāo)志椎咧,發(fā)現(xiàn)中斷標(biāo)志為真時(shí)就中斷掛起,輪詢(xún)標(biāo)志的地方和安全點(diǎn)是重合的把介,跟創(chuàng)建對(duì)象需要分配內(nèi)存的地方也是重合的勤讽。
問(wèn)題4:當(dāng)線(xiàn)程處于Sleep狀態(tài)或Blocking狀態(tài)時(shí),線(xiàn)程無(wú)法響應(yīng)JVM的中斷請(qǐng)求拗踢,從而線(xiàn)程不能“走”到安全點(diǎn)的地方進(jìn)行中斷掛起脚牍,該如何?
【安全區(qū)域巢墅,Safe Region】一段代碼片段中诸狭,引用關(guān)系不會(huì)發(fā)生變化,在這個(gè)區(qū)域中的任意地方開(kāi)始GC都是安全的君纫。
在線(xiàn)程執(zhí)行到Safe Region中的代碼時(shí)驯遇,會(huì)標(biāo)識(shí)自己已經(jīng)進(jìn)入到Safe Region,當(dāng)JVM發(fā)起GC時(shí)蓄髓,就不用管標(biāo)識(shí)自己為Safe Region狀態(tài)的線(xiàn)程了叉庐。當(dāng)線(xiàn)程要離開(kāi)Safe Region時(shí),會(huì)檢測(cè)系統(tǒng)是否完成了GC過(guò)程会喝,如果完成了陡叠,線(xiàn)程就會(huì)繼續(xù)執(zhí)行玩郊,否則它必須等待直到收到可以離開(kāi)Safe Region的信號(hào)為止。