日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

JVM垃圾回收算法 总结及汇总

發(fā)布時(shí)間:2025/3/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM垃圾回收算法 总结及汇总 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

先看一眼JVM虛擬機(jī)運(yùn)行時(shí)的內(nèi)存模型:

?

1.方法區(qū) Perm(永久代、非堆)

2.虛擬機(jī)棧

3.本地方法棧 (Native方法)

4.堆

5.程序計(jì)數(shù)器

?

1 首先的問(wèn)題是:jvm如何知道那些對(duì)象需要回收 ?

目前兩種標(biāo)識(shí)算法三種回收算法、兩種清除算法、三種收集器

  • 引用計(jì)數(shù)法

每個(gè)對(duì)象上都有一個(gè)引用計(jì)數(shù),對(duì)象每被引用一次,引用計(jì)數(shù)器就+1,對(duì)象引用被釋放,引用計(jì)數(shù)器-1,直到對(duì)象的引用計(jì)數(shù)為0,對(duì)象就標(biāo)識(shí)可以回收

這個(gè)可以用數(shù)據(jù)算法中的圖形表示,對(duì)象A-對(duì)象B-對(duì)象C 都有引用,所以不會(huì)被回收,對(duì)象B由于沒(méi)有被引用,沒(méi)有路徑可以達(dá)到對(duì)象B,對(duì)象B的引用計(jì)數(shù)就就是0,對(duì)象B就會(huì)被回收。

?

?

但是這個(gè)算法有明顯的缺陷,對(duì)于循環(huán)引用的情況下,循環(huán)引用的對(duì)象就不會(huì)被回收。例如下圖:對(duì)象A,對(duì)象B 循環(huán)引用,沒(méi)有其他的對(duì)象引用A和B,則A和B 都不會(huì)被回收。

?

  • root搜索算法

這種算法目前定義了幾個(gè)root,也就是這幾個(gè)對(duì)象是jvm虛擬機(jī)不會(huì)被回收的對(duì)象,所以這些對(duì)象引用的對(duì)象都是在使用中的對(duì)象,這些對(duì)象未使用的對(duì)象就是即將要被回收的對(duì)象。簡(jiǎn)單就是說(shuō):如果對(duì)象能夠達(dá)到root,就不會(huì)被回收,如果對(duì)象不能夠達(dá)到root,就會(huì)被回收。

如下圖:對(duì)象D訪問(wèn)不到根對(duì)象,所以就會(huì)被回收

以下對(duì)象會(huì)被認(rèn)為是root對(duì)象:

  • 被啟動(dòng)類(lèi)(bootstrap加載器)加載的類(lèi)和創(chuàng)建的對(duì)象
  • jvm運(yùn)行時(shí)方法區(qū)類(lèi)靜態(tài)變量(static)引用的對(duì)象
  • jvm運(yùn)行時(shí)方法去常量池引用的對(duì)象
  • jvm當(dāng)前運(yùn)行線程中的虛擬機(jī)棧變量表引用的對(duì)象
  • 本地方法棧中(jni)引用的對(duì)象

由于這種算法即使存在互相引用的對(duì)象,但如果這兩個(gè)對(duì)象無(wú)法訪問(wèn)到根對(duì)象,還是會(huì)被回收。如下圖:對(duì)象C和對(duì)象D互相引用,但是由于無(wú)法訪問(wèn)根,所以會(huì)被回收。

jvm在確定是否回收的對(duì)象的時(shí)候采用的是root搜索算法來(lái)實(shí)現(xiàn)。

在root搜索算法的里面,我們說(shuō)的引用這里都指定的是強(qiáng)引用關(guān)系。所謂強(qiáng)引用關(guān)系,就是通過(guò)用new 方式創(chuàng)建的對(duì)象,并且顯示關(guān)聯(lián)的對(duì)象

[java]?view plain?copy
  • <span?style="font-family:Microsoft?YaHei;font-size:14px;"><span?style="font-family:Microsoft?YaHei;font-size:14px;">Object?obj?=?new?Object();</span></span>??

  • 以上就是代表的是強(qiáng)引用關(guān)系,變量obj 強(qiáng)引用了 Object的一個(gè)對(duì)象。

    java里面有四種應(yīng)用關(guān)系,從強(qiáng)到弱分別為:

    Strong Reference(強(qiáng)引用) –>Weak Reference (弱引用) -> Soft Reference(軟引用) – > Phantom Reference(引用)

    ?

    Strong Reference : 只有在引用對(duì)象root不可達(dá)的情況下才會(huì)標(biāo)識(shí)為可回收,垃圾回收才可能進(jìn)行回收

    Weak Reference :即使在root算法中 其引用的對(duì)象root可達(dá)到,但是如果jvm堆內(nèi)存 不夠的時(shí)候,還是會(huì)被回收。

    Soft Reference : 無(wú)論其引用的對(duì)象是否root可達(dá),在響應(yīng)內(nèi)存需要時(shí),由垃圾回收判斷是否需要回收。

    Phantom Reference :在回收器確定其指示對(duì)象可另外回收之后,被加入垃圾回收隊(duì)列.

    ?

    ?

    • 標(biāo)記-清除

    標(biāo)記清除的算法最簡(jiǎn)單,主要是標(biāo)記出來(lái)需要回收的對(duì)象,然后然后把這些對(duì)象在內(nèi)存的信息清除。如何標(biāo)記需要回收的對(duì)象,在上一篇文章里面已經(jīng)有說(shuō)明。

    ?

    • 標(biāo)記-清除-壓縮

    這個(gè)算法是在標(biāo)記-清除的算法之上進(jìn)行一下壓縮空間,重新移動(dòng)對(duì)象的過(guò)程。因?yàn)闃?biāo)記清除算法會(huì)導(dǎo)致很多的留下來(lái)的內(nèi)存空間碎片,隨著碎片的增多,嚴(yán)重影響內(nèi)存讀寫(xiě)的性能,所以在標(biāo)記-清除之后,會(huì)對(duì)內(nèi)存的碎片進(jìn)行整理。最簡(jiǎn)單的整理就是把對(duì)象壓縮到一邊,留出另一邊的空間。由于壓縮空間需要一定的時(shí)間,會(huì)影響垃圾收集的時(shí)間。

    ?

    • 標(biāo)記-清除-復(fù)制

    這個(gè)算法是吧內(nèi)存分配為兩個(gè)空間,一個(gè)空間(A)用來(lái)負(fù)責(zé)裝載正常的對(duì)象信息,,另外一個(gè)內(nèi)存空間(B)是垃圾回收用的。每次把空間A中存活的對(duì)象全部復(fù)制到空間B里面,在一次性的把空間A刪除。這個(gè)算法在效率上比標(biāo)記-清除-壓縮高,但是需要兩塊空間,對(duì)內(nèi)存要求比較大,內(nèi)存的利用率比較低。適用于短生存期的對(duì)象,持續(xù)復(fù)制長(zhǎng)生存期的對(duì)象則導(dǎo)致效率降低

    ?

    由于現(xiàn)在的處理器都是多核的,處理器的性能得到了極大的提升,所以在此基礎(chǔ)上有產(chǎn)生了幾種垃圾收集算法。主要包括兩種算法

    • 并行標(biāo)記清除

    所謂并行,就是原來(lái)垃圾回收只是一個(gè)線程進(jìn)行。現(xiàn)在創(chuàng)建多個(gè)垃圾回收線程。并行的進(jìn)行標(biāo)記和清除。比如把需要標(biāo)記的對(duì)象平均分配到多個(gè)線程之后,當(dāng)標(biāo)記完成之后,多個(gè)線程進(jìn)行清除。

    ?

    • 并發(fā)標(biāo)記清除

    所謂并發(fā),就是應(yīng)用程序和垃圾回收可以同時(shí)執(zhí)行。在標(biāo)記清除算法中,在標(biāo)記對(duì)象和清除對(duì)象,以及壓縮對(duì)象的情況下是需要暫停應(yīng)用的。那么并行標(biāo)記清除壓縮算法則是在標(biāo)記清除壓縮算法的基礎(chǔ)上,把標(biāo)記清除壓縮算法分為以下幾個(gè)過(guò)程

    初始標(biāo)記->并發(fā)標(biāo)記->重新標(biāo)記->并發(fā)清除->重置

    ?

    以上幾種算法是垃圾回收的基本算法,jvm垃圾回收就是在以上幾種算法為基礎(chǔ)的,在以上幾種算法的基礎(chǔ)上,java垃圾回收器可以分為以下幾種:

    • 串行收集器

    用單線程處理所有垃圾回收工作,因?yàn)闊o(wú)需多線程交互,所以效率比較高。但是,也無(wú)法使用多處理器的優(yōu)勢(shì),所以此收集器適合單處理器機(jī)器

    單線程收集器。在目前多核服務(wù)器端運(yùn)行的情況下,效率比較低。比較適合堆內(nèi)存小的情況下使用。

    • 并行收集器

    用多線程處理所有垃圾回收工作,利用多核處理器的優(yōu)勢(shì)。但是如果線程數(shù)量過(guò)多,導(dǎo)致線程之間頻繁調(diào)度,也會(huì)影響性能。一半并行收集的線程是處理器的個(gè)數(shù)。

    “對(duì)吞吐量有高要求”,多CPU、對(duì)應(yīng)用響應(yīng)時(shí)間無(wú)要求的中、大型應(yīng)用。舉例:后臺(tái)處理、科學(xué)計(jì)算。

    • 并發(fā)收集器

    并發(fā)收集器主要減少年老代的暫停時(shí)間,他在應(yīng)用不停止的情況下使用獨(dú)立的垃圾回收線程,跟蹤可達(dá)對(duì)象。在每個(gè)年老代垃圾回收周期中,在收集初期并發(fā)收集器 會(huì)對(duì)整個(gè)應(yīng)用進(jìn)行簡(jiǎn)短的暫停(初始標(biāo)記的過(guò)程),在收集中還會(huì)再暫停一次。第二次暫停會(huì)比第一次稍長(zhǎng)(重新標(biāo)記的過(guò)程),在此過(guò)程中多個(gè)線程同時(shí)進(jìn)行垃圾回收工作。

    并發(fā)收集器使用處理器換來(lái)短暫的停頓時(shí)間。在一個(gè)N個(gè)處理器的系統(tǒng)上,并發(fā)收集部分使用K/N個(gè)可用處理器進(jìn)行回收,一般情況下1<=K<=N/4。

    在只有一個(gè)處理器的主機(jī)上使用并發(fā)收集器,設(shè)置為incremental mode模式也可獲得較短的停頓時(shí)間。

    浮動(dòng)垃圾:由于在應(yīng)用運(yùn)行的同時(shí)進(jìn)行垃圾回收,所以有些垃圾可能在垃圾回收進(jìn)行完成時(shí)產(chǎn)生,這樣就造成了“Floating Garbage”,這些垃圾需要在下次垃圾回收周期時(shí)才能回收掉。所以,并發(fā)收集器一般需要20%的預(yù)留空間用于這些浮動(dòng)垃圾。

    Concurrent Mode Failure:并發(fā)收集器在應(yīng)用運(yùn)行時(shí)進(jìn)行收集,所以需要保證堆在垃圾回收的這段時(shí)間有足夠的空間供程序使用,否則,垃圾回收還未完成,堆空間先滿(mǎn)了。這種情況下將會(huì)發(fā)生“并發(fā)模式失敗”,此時(shí)整個(gè)應(yīng)用將會(huì)暫停,進(jìn)行垃圾回收。

    并發(fā)收集器,在垃圾回收的時(shí)候采用并發(fā)標(biāo)記清除算法的收集器

    對(duì)響應(yīng)時(shí)間要求高的,多CPU,大型應(yīng)用。比如頁(yè)面請(qǐng)求/web服務(wù)器。前端業(yè)務(wù)系統(tǒng)用的比較多。

    ?

    串行處理器:

    --適用情況:數(shù)據(jù)量比較小(100M左右);單處理器下并且對(duì)響應(yīng)時(shí)間無(wú)要求的應(yīng)用。

    --缺點(diǎn):只能用于小型應(yīng)用

    并行處理器:

    --適用情況:“對(duì)吞吐量有高要求”,多CPU、對(duì)應(yīng)用響應(yīng)時(shí)間無(wú)要求的中、大型應(yīng)用。舉例:后臺(tái)處理、科學(xué)計(jì)算。

    --缺點(diǎn):垃圾收集過(guò)程中應(yīng)用響應(yīng)時(shí)間可能加長(zhǎng)

    并發(fā)處理器:

    --適用情況:“對(duì)響應(yīng)時(shí)間有高要求”,多CPU、對(duì)應(yīng)用響應(yīng)時(shí)間有較高要求的中、大型應(yīng)用。舉例:Web服務(wù)器/應(yīng)用服務(wù)器、電信交換、集成開(kāi)發(fā)環(huán)境。

    JDK5.0適用的分代垃圾回收算法

    ?????? 分代的垃圾回收策略,是基于這樣一個(gè)事實(shí):不同的對(duì)象的生命周期是不一樣的。因此,不同生命周期的對(duì)象可以采取不同的收集方式,以便提高回收效率。

    ?????? 在Java程序運(yùn)行的過(guò)程中,會(huì)產(chǎn)生大量的對(duì)象,其中有些對(duì)象是與業(yè)務(wù)信息相關(guān),比如Http請(qǐng)求中的Session對(duì)象、線程、Socket連接,這類(lèi)對(duì)象跟業(yè)務(wù)直接掛鉤,因此生命周期比較長(zhǎng)。但是還有一些對(duì)象,主要是程序運(yùn)行過(guò)程中生成的臨時(shí)變量,這些對(duì)象生命周期會(huì)比較短,比如:String對(duì)象,由于其不變類(lèi)的特性,系統(tǒng)會(huì)產(chǎn)生大量的這些對(duì)象,有些對(duì)象甚至只用一次即可回收。

    ?????? 試想,在不進(jìn)行對(duì)象存活時(shí)間區(qū)分的情況下,每次垃圾回收都是對(duì)整個(gè)堆空間進(jìn)行回收,花費(fèi)時(shí)間相對(duì)會(huì)長(zhǎng),同時(shí),因?yàn)槊看位厥斩夹枰闅v所有存活對(duì)象,但實(shí)際上,對(duì)于生命周期長(zhǎng)的對(duì)象而言,這種遍歷是沒(méi)有效果的,因?yàn)榭赡苓M(jìn)行了很多次遍歷,但是他們依舊存在。因此,分代垃圾回收采用分治的思想,進(jìn)行代的劃分,把不同生命周期的對(duì)象放在不同代上,不同代上采用最適合它的垃圾回收方式進(jìn)行回收。

    如何分代

    如圖所示:

    ?????? 虛擬機(jī)中的共劃分為三個(gè)代:年輕代(Young Generation)年老點(diǎn)(Old Generation)持久代(Permanent Generation)。其中持久代主要存放的是Java類(lèi)的類(lèi)信息,與垃圾收集要收集的Java對(duì)象關(guān)系不大。年輕代和年老代的劃分是對(duì)垃圾收集影響比較大的。

    年輕代:

    ????? 所有新生成的對(duì)象首先都是放在年輕代的。年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。年輕代分三個(gè)區(qū)。一個(gè)Eden區(qū),兩個(gè)Survivor區(qū)(一般而言)。大部分對(duì)象在Eden區(qū)中生成。當(dāng)Eden區(qū)滿(mǎn)時(shí),還存活的對(duì)象將被復(fù)制到Survivor區(qū)(兩個(gè)中的一個(gè)),當(dāng)這個(gè)Survivor區(qū)滿(mǎn)時(shí),此區(qū)的存活對(duì)象將被復(fù)制到另外一個(gè)Survivor區(qū),當(dāng)這個(gè)Survivor去也滿(mǎn)了的時(shí)候,從第一個(gè)Survivor區(qū)復(fù)制過(guò)來(lái)的并且此時(shí)還存活的對(duì)象,將被復(fù)制“年老區(qū)(Tenured)”。需要注意,Survivor的兩個(gè)區(qū)是對(duì)稱(chēng)的,沒(méi)先后關(guān)系,所以同一個(gè)區(qū)中可能同時(shí)存在從Eden復(fù)制過(guò)來(lái) 對(duì)象,和從前一個(gè)Survivor復(fù)制過(guò)來(lái)的對(duì)象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過(guò)來(lái)的對(duì)象。而且,Survivor區(qū)總有一個(gè)是空的。同時(shí),根據(jù)程序需要,Survivor區(qū)是可以配置為多個(gè)的(多于兩個(gè)),這樣可以增加對(duì)象在年輕代中的存在時(shí)間,減少被放到年老代的可能。

    年老代:

    ????? 在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。因此,可以認(rèn)為年老代中存放的都是一些生命周期較長(zhǎng)的對(duì)象。

    持久代:

    ????? 用于存放靜態(tài)文件,如今Java類(lèi)、方法等。持久代對(duì)垃圾回收沒(méi)有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來(lái)存放這些運(yùn)行過(guò)程中新增的類(lèi)。持久代大小通過(guò)-XX:MaxPermSize=&lt;N>進(jìn)行設(shè)置。

    什么情況下觸發(fā)垃圾回收

    由于對(duì)象進(jìn)行了分代處理,因此垃圾回收區(qū)域、時(shí)間也不一樣。GC有兩種類(lèi)型:Scavenge GC和Full GC。

    ?

    (1)新生代上的GC實(shí)現(xiàn) ? Serial:單線程的收集器,只使用一個(gè)線程進(jìn)行收集,并且收集時(shí)會(huì)暫停其他所有 工作線程(Stop the world)。它是Client模式下的默認(rèn)新生代收集器。 ? ParNew:Serial收集器的多線程版本。在單CPU甚至兩個(gè)CPU的環(huán)境下,由于線程 交互的開(kāi)銷(xiāo),無(wú)法保證性能超越Serial收集器。 ? Parallel Scavenge:也是多線程收集器,與ParNew的區(qū)別是,它是吞吐量優(yōu)先 收集器。吞吐量=運(yùn)行用戶(hù)代碼時(shí)間/(運(yùn)行用戶(hù)代碼+垃圾收集時(shí)間)。另一點(diǎn)區(qū)別 是配置-XX:+UseAdaptiveSizePolicy后,虛擬機(jī)會(huì)自動(dòng)調(diào)整Eden/Survivor等參數(shù)來(lái) 提供用戶(hù)所需的吞吐量。我們需要配置的就是內(nèi)存大小-Xmx和吞吐量GCTimeRatio。 ? (2)老年代上的GC實(shí)現(xiàn) ? Serial Old:Serial收集器的老年代版本。 ? Parallel Old:Parallel Scavenge的老年代版本。此前,如果新生代采用PS GC的話, 老年代只有Serial Old能與之配合。現(xiàn)在有了Parallel Old與之配合,可以在注重吞吐量 及CPU資源敏感的場(chǎng)合使用了。 ? CMS:采用的是標(biāo)記-清除而非標(biāo)記-整理,是一款并發(fā)低停頓的收集器。但是由于 采用標(biāo)記-清除,內(nèi)存碎片問(wèn)題不可避免。可以使用-XX:CMSFullGCsBeforeCompaction 設(shè)置執(zhí)行幾次CMS回收后,跟著來(lái)一次內(nèi)存碎片整理。

    ?

    GC類(lèi)型?
    GC有兩種類(lèi)型:Scavenge GC和Full GC。?

    1. Scavenge GC?

    一般情況下,當(dāng)新對(duì)象生成,并且在Eden申請(qǐng)空間失敗時(shí),就好觸發(fā)Scavenge GC,堆Eden區(qū)域進(jìn)行GC,清除非存活對(duì)象,并且把尚且存活的對(duì)象移動(dòng)到Survivor區(qū)。然后整理Survivor的兩個(gè)區(qū)。?
    2. Full GC?
    對(duì)整個(gè)堆進(jìn)行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此應(yīng)該盡可能減少Full GC。有如下原因可能導(dǎo)致Full GC:?
    * Tenured被寫(xiě)滿(mǎn)?
    * Perm域被寫(xiě)滿(mǎn)?
    * System.gc()被顯示調(diào)用?
    * 上一次GC之后Heap的各域分配策略動(dòng)態(tài)變化?

    ?

    ?

    ?

    ?

    ?

    ?

    ?




    http://m.blog.csdn.net/blog/zhao9tian/39121819 from:http://blog.csdn.net/xiaomin1991222/article/details/50981410
    《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

    以上是生活随笔為你收集整理的JVM垃圾回收算法 总结及汇总的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。