垃圾回收器
什么是垃圾對(duì)象?
沒有任何引用的對(duì)象。
如何發(fā)現(xiàn)垃圾對(duì)象赊锚?
- reference count 引用計(jì)數(shù)
- 每引用一次給計(jì)數(shù)器+1,減少一次引用進(jìn)行-1屉栓。
- 無法解決的問題舷蒲,循環(huán)引用。A引用B友多,B引用C牲平,C引用A,但是ABC三個(gè)整體沒有被其他的引用域滥。 ABC整體應(yīng)該是一個(gè)垃圾纵柿,引用計(jì)數(shù)無法發(fā)現(xiàn)。
- root search 根可達(dá)算法
- 從線程對(duì)象(main方法)出發(fā)搜索對(duì)象是否可達(dá)启绰。
- 從靜態(tài)變量出發(fā)昂儒。
- 常量池
-
JNI指針,c++實(shí)現(xiàn)的本地方法
GC Algorithms 垃圾清除算法
- Mark-Sweep (標(biāo)記清除)將不可用的對(duì)象標(biāo)記委可,然后清除渊跋。
- 優(yōu)點(diǎn):
- 算法實(shí)現(xiàn)簡(jiǎn)單
- 存活對(duì)象較多時(shí)效率較高
- 缺點(diǎn)
- 掃描兩遍(第一次找出不可用對(duì)象并標(biāo)記,第二遍遍歷清除)效率較低
- 容易產(chǎn)生碎片
- 優(yōu)點(diǎn):
- copy(拷貝)將內(nèi)存一份為二着倾,將可用的對(duì)象拷貝到一塊區(qū)域刹枉。
- 優(yōu)點(diǎn):
- 對(duì)象存活較少的情況下只掃描一遍,效率較高
- 沒有碎片
- 缺點(diǎn):
- 浪費(fèi)空間
- 移動(dòng)復(fù)制對(duì)象屈呕,需要調(diào)整對(duì)象引用
- 優(yōu)點(diǎn):
- Mark-Compact (標(biāo)記壓縮)將可用對(duì)象移動(dòng)至內(nèi)存的某個(gè)區(qū)域微宝,剩下的就是大塊的不可用的區(qū)域,再刪除不可用的虎眨。
- 優(yōu)點(diǎn)
- 不會(huì)產(chǎn)生內(nèi)存碎片蟋软,方便對(duì)象分配
- 不會(huì)內(nèi)存減半
- 缺點(diǎn)
- 掃描兩次效率較低
- 需要移動(dòng)對(duì)象,效率較低
- 優(yōu)點(diǎn)
堆內(nèi)存邏輯分區(qū)(不適合不分代的垃圾收集器,除Epsilon嗽桩、ZGC岳守、shenandoah之外都是邏輯分代模型,G1是邏輯分代不是物理分代碌冶,除此之外不僅邏輯分代而且還是 物理分代)
- 新生代:大量死去少量存活湿痢,采用的復(fù)制算法。eden、survivor1譬重、survivor2默認(rèn)比例是8:1
- eden:初生代
- survivor:有兩塊survivor區(qū)域
- 老年代:有大量存活拒逮,少量死亡,采用ms(Mark swap標(biāo)記清除)或mc(Mark compact 標(biāo)記壓縮)算法臀规。
- tenured:老年代或者叫永久代滩援。
一個(gè)對(duì)象的消亡過程
- 嘗試在棧上分配
- 能在棧分配必須滿足:
- 線程私有小對(duì)象
- 無逃逸
- 支持標(biāo)量替換(對(duì)象可以一個(gè)或多個(gè)基本類型替換)
- 能在棧分配必須滿足:
對(duì)象的生命周期會(huì)隨著方法的調(diào)用開始而開始,方法的調(diào)用結(jié)束而結(jié)束塔嬉,對(duì)于這種對(duì)象玩徊,是不是該考慮將對(duì)象不在分配在堆空間中呢?因?yàn)橐坏┓峙湓诙芽臻g中谨究,當(dāng)方法調(diào)用結(jié)束恩袱,沒有了引用指向該對(duì)象,該對(duì)象就需要被gc回收胶哲,而如果存在大量的這種情況畔塔,對(duì)gc來說無疑是一種負(fù)擔(dān)
- 進(jìn)入Eden
- Eden 區(qū)默認(rèn)1%的區(qū)域有個(gè)叫TLAB(Thread Local Allocation Buffer)多線程不用競(jìng)爭(zhēng)就可以申請(qǐng)空間提高效率。
- Eden存活下來,進(jìn)入survivor1
- survivor1存活下來進(jìn)入survivor2
- survivor2存活下來進(jìn)入survivor1如此往復(fù)纪吮,指導(dǎo)達(dá)到配置好的代數(shù),后進(jìn)入老年代萎胰。
MiniorGC/YGC: 年輕代空間耗盡觸發(fā)碾盟。
MajorGC/FullGC:老年代空間不足,觸發(fā)年輕代和老年代同時(shí)回收
對(duì)象何時(shí)進(jìn)入老年代
- 超過-XX:MaxTenuringThreshold 指定數(shù)值
- PS 15
- CMS 5
- G1 15
- 動(dòng)態(tài)年齡
- Survivor(Eden + s1 +s2)區(qū)的對(duì)象年齡從小到大進(jìn)行累加技竟,當(dāng)累加到 X 年齡時(shí)的總和大于50%(可以使用-XX:TargetSurvivorRatio=? 來設(shè)置保留多少空閑空間冰肴,默認(rèn)值是50),那么比X大的都會(huì)晉升到老年代
- 分配擔(dān)保
在發(fā)生minor gc之前榔组,虛擬機(jī)會(huì)檢測(cè) : 老年代最大可用的連續(xù)空間 > 新生代all對(duì)象總空間熙尉?
1、滿足搓扯,minor gc是安全的检痰,可以進(jìn)行minor gc。
2锨推、不滿足铅歼,虛擬機(jī)查看HandlePromotionFailure參數(shù):- 為true,允許擔(dān)保失敗换可,會(huì)繼續(xù)檢測(cè)老年代最大可用的連續(xù)空間>歷次晉升到老年代對(duì)象的平均大小椎椰。若大于,將嘗試進(jìn)行一次minor gc沾鳄,若失敗慨飘,則重新進(jìn)行一次full gc。
- 為false译荞,則不允許冒險(xiǎn)瓤的,要進(jìn)行full gc(對(duì)老年代進(jìn)行g(shù)c)休弃。
常見的垃圾回收器
Serial收集器
Serial收集器是最基礎(chǔ)、歷史最悠久的收集器堤瘤,曾經(jīng)(在JDK 1.3.1之前)是HotSpot虛擬機(jī)新生代 收集器的唯一選擇玫芦。是個(gè)單線程的垃圾回收器,這里的單線程強(qiáng)調(diào)的不是這個(gè)回收器是由一個(gè)核心的一個(gè)線程完成本辐,強(qiáng)調(diào)的是“stop the world”桥帆,該垃圾回收線程工作時(shí)必須停掉其他工作線程。
適用場(chǎng)景:對(duì)于單核處理器或處理器核心數(shù)較少的環(huán)境來說慎皱,Serial收集器由于沒有線程交互的開銷老虫,專心做垃圾收集自然可以獲得最高的單線程收集效率。
類型:新生代回收器
ParNew收集器
是Serial收集器的多線程并行版本茫多,ParNew收集器實(shí)質(zhì)上是Serial收集器的多線程并行版本督笆,除了同時(shí)使用多條線程進(jìn)行垃圾收集之外 确镊, 其余的行為包括Serial收集器可用的所有控制參數(shù)(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)嫂伞、收集算法、Stop The World季二、對(duì)象分配規(guī)則狐粱、回收策略等都與Serial收集器完全一致但它卻是不少運(yùn)行在服務(wù)端模式下的HotSpot虛擬機(jī),經(jīng)管如此斑唬,尤其在jdk7之前還是有大量的服務(wù)端適用的是ParNew市埋,重要原因就是只有它可以配合CMS使用。
類型:新生代回收器
適用場(chǎng)景:ParNew+CMS 第一款真正意義上支持并發(fā)的垃圾收集器恕刘,它首次 實(shí)現(xiàn)了讓垃圾收集線程與用戶線程(基本上)同時(shí)工作缤谎。
并行(Parallel):并行描述的是多條垃圾收集器線程之間的關(guān)系,說明同一時(shí)間有多條這樣的線 程在協(xié)同工作褐着,通常默認(rèn)此時(shí)用戶線程是處于等待狀態(tài)坷澡。
并發(fā)(Concurrent):并發(fā)描述的是垃圾收集器線程與用戶線程之間的關(guān)系,說明同一時(shí)間垃圾 收集器線程與用戶線程都在運(yùn)行含蓉。由于用戶線程并未被凍結(jié)洋访,所以程序仍然能響應(yīng)服務(wù)請(qǐng)求,但由于 垃圾收集器線程占用了一部分系統(tǒng)資源谴餐,此時(shí)應(yīng)用程序的處理的吞吐量將受到一定影響姻政。
Parallel Scavenge收集器
Parallel Scavenge收集器的特點(diǎn)是它的關(guān)注點(diǎn)與其他收集器不同,CM S等收集器的關(guān)注點(diǎn)是盡可能 地縮短垃圾收集時(shí)用戶線程的停頓時(shí)間岂嗓,而Parallel Scavenge收集器的目標(biāo)則是達(dá)到一個(gè)可控制的吞吐 量(Throughput)汁展。
- -XX:MaxGCPauseMillis 控制最大垃圾收集停頓時(shí)間
- -XX:GCTimeRatio 直接設(shè)置吞吐量
適用場(chǎng)景:優(yōu)先考慮吞吐量的應(yīng)用,而不是STW時(shí)間。
類型:新生代垃圾回收器
Serial Old收集器
Serial Old是一個(gè)使用標(biāo)記整理算法的單線程收集器食绿。這個(gè)垃圾回收器主要也是提供給客戶端模式下使用的侈咕,Parallel Scavenge收集器架構(gòu)中本身有PS MarkSweep收集器來進(jìn)行老年代收集,并非直接調(diào)用Serial Old收集器器紧,PS MarkSweep收集器與Serial Old的實(shí)現(xiàn)幾乎是一樣的耀销,所以在官方的許多資料中都是直接以Serial Old代替PS MarkSweep進(jìn)行講解。
適用場(chǎng)景:?jiǎn)魏颂幚砥骰蛱幚砥骱诵臄?shù)較少的環(huán)境铲汪,內(nèi)存也不是特別大的場(chǎng)景熊尉。
類型:老年代回收器
Parallel Old收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,支持多線程并發(fā)收集掌腰,基于標(biāo)記-整理算法實(shí) 現(xiàn)狰住。這個(gè)收集器是直到JDK 6時(shí)才開始提供的,在此之前使用Parallel Scavenge只能選擇Serial Old(PS MarkSweep)其他表現(xiàn)性能較好的如CMS無法使用齿梁,由于Serial Old表現(xiàn)并不突出催植,所以使用Parallel Scavenge并不能獲得吞吐量上的提升。
適用場(chǎng)景:搭配Parallel Scavenge使用
類型:老年代回收器
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器勺择。更短的停頓時(shí)間可以獲的更短的響應(yīng)時(shí)間创南。收集過程包括以下幾個(gè)部分
- 初始標(biāo)記(CMS initial mark)
- 并發(fā)標(biāo)記(CM S concurrent mark)
- 重新標(biāo)記(CM S remark)
- 并發(fā)清除(CM S concurrent sweep)
常見垃圾回收器組合參數(shù)設(shè)定:(1.8)
- -XX:+UseSerialGC = Serial New (DefNew) + Serial Old
- 小型程序。默認(rèn)情況下不會(huì)是這種選項(xiàng)省核,HotSpot會(huì)根據(jù)計(jì)算及配置和JDK版本自動(dòng)選擇收集器
- -XX:+UseParNewGC = ParNew + SerialOld
- 這個(gè)組合已經(jīng)很少用(在某些版本中已經(jīng)廢棄)
- https://stackoverflow.com/questions/34962257/why-remove-support-for-parnewserialold-anddefnewcms-in-the-future
- -XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old
- -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默認(rèn)) 【PS + SerialOld】
- -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old
- -XX:+UseG1GC = G1
- Linux中沒找到默認(rèn)GC的查看方法稿辙,而windows中會(huì)打印UseParallelGC
- java +XX:+PrintCommandLineFlags -version
- 通過GC的日志來分辨
- Linux下1.8版本默認(rèn)的垃圾回收器到底是什么?
- 1.8.0_181 默認(rèn)(看不出來)Copy MarkCompact
- 1.8.0_222 默認(rèn) PS + PO