惠州網(wǎng)站建設(shè)網(wǎng)站app拉新平臺(tái)
文章目錄
- 1.垃圾回收算法
- **1.1. 標(biāo)記階段**
- **1.2. 清除階段**
- 1.2.1.標(biāo)記清除算法
- 1.2.2.標(biāo)記復(fù)制算法
- 1.2.3.標(biāo)記整理算法
- 1.3.引用
- 2.常見(jiàn)的垃圾回收器
- 2.1.Serial回收器
- 2.2.ParNew回收器
- 2.3.Parallel回收器
- 2.4.CMS回收器
- <font color = red>2.5.G1垃圾回收器
- ZGC回收器(實(shí)驗(yàn))
1.垃圾回收算法
首先,我們需要明確的是,垃圾回收主要包括以下幾個(gè)階段1.1. 標(biāo)記階段
在標(biāo)記階段,我們舉例兩個(gè)算法
1.引用計(jì)數(shù)算法
這個(gè)算法是python
使用的標(biāo)記算法。
什么是引用計(jì)數(shù)算法:給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值加1;當(dāng)引用失效時(shí),計(jì)數(shù)器值減1,引用數(shù)量為0的時(shí)候,則說(shuō)明對(duì)象沒(méi)有被任何引用指向,可以認(rèn)定是”垃圾”對(duì)象
這種方法實(shí)現(xiàn)比較簡(jiǎn)單,且效率很高,但是無(wú)法解決循環(huán)引用的問(wèn)題,因此在java中沒(méi)有采用此算法(但是在Python中采用的是此算法)
2.可達(dá)性分析算法
這個(gè)算法是java
使用的標(biāo)記算法。
可達(dá)性分析算法的基本思路就是通過(guò)一系列名為”GC Roots”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索,搜索所走過(guò)的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí),則證明此對(duì)象是不可用的。
這個(gè)算法的基本思想是通過(guò)一系列稱為“GC Roots”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)向下搜索,搜索所走過(guò)的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈(即GC Roots到對(duì)象不可達(dá))時(shí),則證明此對(duì)象是不可用的。
2.1.對(duì)象的finalization機(jī)制
這個(gè)機(jī)制我稱之為救贖機(jī)制
,當(dāng)對(duì)象不可達(dá)的時(shí)候是且僅有一次救贖的機(jī)會(huì)的,如果這個(gè)方法重寫(xiě)過(guò)且沒(méi)執(zhí)行過(guò),就會(huì)執(zhí)行該方法。
如果這個(gè)對(duì)象被判定為有必要執(zhí)行finalize()方法,那么這個(gè)對(duì)象將會(huì)放置在一個(gè)叫做F-Queuc的隊(duì)列之中,并在稍后由一個(gè)由虛擬機(jī)自動(dòng)建立的、低優(yōu)先級(jí)的Finalizer線程去執(zhí)行它。
1.2. 清除階段
1.2.1.標(biāo)記清除算法
當(dāng)堆中的有效內(nèi)存空間(available memory)被耗盡的時(shí)候,就會(huì)停止整個(gè)程序(也被稱為stop the world),然后進(jìn)行兩項(xiàng)工作,第一項(xiàng)則是標(biāo)記,第二項(xiàng)則是清除。
- 標(biāo)記:collector從引用根節(jié)點(diǎn)開(kāi)始遍歷,標(biāo)記所有被引用的對(duì)象。一般是在對(duì)象的Header中記錄為可達(dá)對(duì)象。
- 清除:collector對(duì)堆內(nèi)存從頭到尾進(jìn)行線性的遍歷,如果發(fā)現(xiàn)某個(gè)對(duì)象在其Header中沒(méi)有標(biāo)記為可達(dá)對(duì)象,則將其回收。
1.2.2.標(biāo)記復(fù)制算法
- 將內(nèi)存分為大小相同的兩塊,每次使用其中的一塊。當(dāng)這一塊的內(nèi)存使用完后,就將還存活的對(duì)象復(fù)制另一塊去,然后再把使用的空間一次清理掉。
優(yōu)點(diǎn):
1.不會(huì)出現(xiàn)內(nèi)存碎片問(wèn)題
2.對(duì)于存活對(duì)象少的區(qū)域(新生代),簡(jiǎn)單高效
缺點(diǎn):
1.浪費(fèi)空間并且移動(dòng)對(duì)象開(kāi)銷(xiāo)大
1.2.3.標(biāo)記整理算法
根據(jù)老年代的特點(diǎn)特出的一種標(biāo)記算法,標(biāo)記過(guò)程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象回收,而是讓所有存活的對(duì)象向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。
優(yōu)點(diǎn):
1.消除了標(biāo)記-清除算法中,內(nèi)存區(qū)域分散不連續(xù)的缺點(diǎn),
2.消除了復(fù)制算法中內(nèi)存減半的高額代價(jià)
缺點(diǎn):
1.移動(dòng)對(duì)象開(kāi)銷(xiāo)較大
1.3.引用
內(nèi)存溢出的原因:存在大量無(wú)用的但又有強(qiáng)引用的對(duì)象無(wú)法回收
下面介紹java存在的4種引用:
1.強(qiáng)引用
我們經(jīng)常使用的引用都是強(qiáng)引用,強(qiáng)引用觸及的對(duì)象,即便程序報(bào)錯(cuò)也不可能回收 。
2.軟引用
在程序要內(nèi)存溢出之前,會(huì)把軟引用對(duì)象列入二次回收范圍,如果本次回收內(nèi)存仍然不足以運(yùn)行程序,則會(huì)把軟引用對(duì)象回收,一般用于高速緩存。
3.弱引用
發(fā)現(xiàn)即回收,生存到下次內(nèi)存回收之前,一般用于可有可無(wú)的緩存。
4.虛引用
對(duì)程序完全無(wú)影響,但是在回收之后可以收到通知
2.常見(jiàn)的垃圾回收器
垃圾回收器的性能指標(biāo):
1:吞吐量:即程序運(yùn)行時(shí)間占總時(shí)間的百分比。
2:低延時(shí):單次暫停的時(shí)間。
二者屬于互斥狀態(tài),二者不可得兼
低延遲會(huì)縮短回收時(shí)間,因而會(huì)進(jìn)行更多回收準(zhǔn)備的無(wú)用功,因此吞吐量會(huì)對(duì)吞吐量產(chǎn)生負(fù)面影響。
注意:CMS在JDK9已經(jīng)廢棄,畫(huà)虛線的表示在后來(lái)發(fā)行版本組個(gè)方式已經(jīng)廢棄
2.1.Serial回收器
這個(gè)收集器是一個(gè)單線程的收集器,但它的“單線程”的意義并不僅僅說(shuō)明它只會(huì)使用一個(gè)CPU或一條收集線程去完成垃圾收集工作,更重要的是在它進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程,直到它收集結(jié)束(stop The world)。
- serial收集器是最基本、歷史最悠久的垃圾收集器了。JDK1.3之前回收新生代唯一的選擇。
- serial收集器作為HotSpot中client模式下的默認(rèn)新生代垃圾收集器。serial收集器
采用復(fù)制算法、事行回收和"stop-the-world”機(jī)制
的方式執(zhí)行內(nèi)存回收。 - 除了年輕代之外,serial收集器還提供用于執(zhí)行老年代垃圾收集的serial old收集器。Serial old收集器同樣也采用了串行回收
和"stop the World"機(jī)制,只不過(guò)內(nèi)存回收算法使用的是標(biāo)記-壓縮
算法。 - serial old是運(yùn)行在
client模式
下默認(rèn)的老年代的垃圾回收器 - Serial old在server模式下主要有兩個(gè)用途
- ①與新生代的Parallelscavenge配合使用
- ②作為老年代CMs收集器的后備垃圾收集方案
2.2.ParNew回收器
如果說(shuō)serial cc是年輕代中的單線程垃圾收集器,那么ParNew收集器則是serial收集器的多線程版本。
- ParNew是Parallel的縮寫(xiě),New:只能處理的是新生代
- ParNew收集器除了采用并行回收的方式執(zhí)行內(nèi)存回收外,兩款垃圾收集器之間幾乎沒(méi)有任何區(qū)別。
- ParNew收集器在年輕代中同樣也是采用復(fù)制算法、"stop-the-world"機(jī)制。
- ParNew是很多JVM運(yùn)行在server模式下新生代的默認(rèn)垃圾收集器。
2.3.Parallel回收器
Hotspot的年輕代中除了擁有ParNew收集器是基于并行回收的以外,Parallel Scavenge收集器同樣也采用了復(fù)制算法、并行回收和"stopthe world”機(jī)制。
和ParNew收集器不同,Parallel scavenge收集器的目標(biāo)則是達(dá)
一個(gè)可控制的吞吐量(Throughput),它也被稱為吞吐量?jī)?yōu)先的垃圾收集器。
自適應(yīng)調(diào)節(jié)策略也是Parallel scavenge與ParNew一個(gè)重要區(qū)別。
2.4.CMS回收器
- 垃圾收集共分為五個(gè)階段:上圖所示初始標(biāo)記和重新標(biāo)記會(huì)有STW。
- 重新標(biāo)記,會(huì)用到三色標(biāo)記里的增量更新算法。
- 并發(fā)清理:這個(gè)階段如果有新增對(duì)象會(huì)被標(biāo)記為黑色不做任何處理主要優(yōu)點(diǎn):并發(fā)收集、低停頓。
- 一XX:+UseConcMarkSweepGC:啟用cms
CMS的弊端:
1.會(huì)產(chǎn)生內(nèi)存碎片,導(dǎo)致并發(fā)清除后,用戶線程可用的空間不足。在無(wú)法分配大對(duì)象的情況下,不得不提前觸發(fā)Full GC。
2 .CMS收集器對(duì)cPu資源非常敏感。在并發(fā)階段,它雖然不會(huì)導(dǎo)致用戶停頓,但是會(huì)因?yàn)檎加昧艘徊糠志€程而導(dǎo)致應(yīng)用程序變慢,總吞吐量會(huì)降低。
3.CMS收集器無(wú)法處理浮動(dòng)垃圾??赡艹霈F(xiàn)“Concurrent Mode railure"失敗而導(dǎo)致另一次 Full GC 的產(chǎn)生。在并發(fā)標(biāo)記階段由于程序的工作線程和垃圾收集線程是同時(shí)運(yùn)行或者交叉運(yùn)行的,那么在并發(fā)標(biāo)記階段如果產(chǎn)生新的垃圾對(duì)象,CMs將無(wú)法對(duì)這些垃圾對(duì)象進(jìn)行標(biāo)記,最終會(huì)導(dǎo)致這些新產(chǎn)生的垃圾對(duì)象沒(méi)有被及時(shí)回收,從而只能在下一次執(zhí)行Gc時(shí)釋放這些之前未被回收的內(nèi)存空間。
2.5.G1垃圾回收器
G1垃圾回收器,是前沿成果
原因就在于應(yīng)用程序所應(yīng)對(duì)的業(yè)務(wù)越來(lái)越龐大、復(fù)雜,用戶越來(lái)越多,沒(méi)有cc就不能保證應(yīng)用程序正常進(jìn)行,而經(jīng)常造成STw的Gc又跟不上實(shí)際的需求,所以才會(huì)不斷地嘗試對(duì)cc進(jìn)行優(yōu)化。G1 (Garbage-First)垃圾回收器是在Java7 update 4之后引入的一個(gè)新的垃圾回收器,是當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一。
官方給G1設(shè)定的目標(biāo)是在延遲可控的情況下獲得盡可能高的吞吐量,所以才擔(dān)當(dāng)起“全功能收集器”的重任與期望。
-
因?yàn)镚1是一個(gè)并行回收器,它把堆內(nèi)存分割為很多不相關(guān)的
區(qū)域(Region)
(物理上不連續(xù)的)。使用不同的Region來(lái)表示Eden、幸存者o區(qū),幸存者1區(qū),老年代等。 -
G1 Gc有計(jì)劃地避免在整個(gè)Java堆中進(jìn)行全區(qū)域的垃圾收集。G1跟蹤各個(gè) Region里面的垃圾堆積的價(jià)值大小(回收所獲得的空間大小以及回收所需時(shí)間的經(jīng)驗(yàn)值),在后臺(tái)維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的Region。由于這種方式的側(cè)重點(diǎn)在于回收垃圾最大量的區(qū)間(Region),所以我們給G1一個(gè)名字:
垃圾優(yōu)先(Garbage First) 。
ZGC回收器(實(shí)驗(yàn))
JVM的自動(dòng)垃圾收集雖然減少了開(kāi)發(fā)人員的工作,在一定程度上減少了內(nèi)存泄漏的風(fēng)險(xiǎn),但是由于GC是自動(dòng)進(jìn)行的,一些無(wú)法預(yù)知的事情有時(shí)候可能產(chǎn)生對(duì)應(yīng)用有害的影響。
延遲增加導(dǎo)致應(yīng)用的吞吐量和性能
隨著時(shí)代發(fā)展,硬件會(huì)逐漸便宜,應(yīng)用使用的內(nèi)存將會(huì)越來(lái)越大,但是又不能增加延遲,降低吞吐量
ZGC保證,不管在什么情況下,延遲不會(huì)超過(guò)10毫秒。
ZGC最典型的特性是它是一款并發(fā)(concurrent)的GC,其它的特性如下:
它可以標(biāo)記內(nèi)存,復(fù)制和遷移(relocate)內(nèi)存,所有的操作都是并發(fā)的,同時(shí)它有一個(gè)并發(fā)的引用處理器
其它的垃圾收集器都是使用store barriers,ZGC使用load barriers,用于跟蹤內(nèi)存
lock->unlock->read->load 讀內(nèi)存
use->assign->store->write 寫(xiě)內(nèi)存
- ZGC可以更加靈活的配置大小和策略,相比于G1,它可以更好的處理非常大(very large)對(duì)象的釋放
- ZGC只有一代,沒(méi)有新生代,老年代什么的,但是ZGC可以支持局部壓縮,在內(nèi)存恢復(fù)和遷移(reclaim and relocate)時(shí),ZGC仍然有很高的性能
- ZGC依賴NUMA-aware(非均衡存儲(chǔ)器訪問(wèn)),需要我們的內(nèi)存支持這種特點(diǎn)
大部分圖片以及內(nèi)容總結(jié)自尚硅谷杜紅康老師的尚硅谷宋紅康JVM全套教程(詳解java虛擬機(jī))