欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

新手入門Jvm--Jvm垃圾回收

 更新時(shí)間:2021年06月19日 17:22:35   作者:讓你跑39m哈哈  
JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來(lái)的計(jì)算機(jī),是通過(guò)在實(shí)際的計(jì)算機(jī)上仿真模擬各種計(jì)算機(jī)功能來(lái)實(shí)現(xiàn)的

1. Jvm垃圾回收

Java虛擬機(jī)主要分為五大模塊:類裝載器子系統(tǒng)、運(yùn)行時(shí)數(shù)據(jù)區(qū)、執(zhí)行引擎、本地方法接口和垃圾收集模塊。其中垃圾收集模塊在Java虛擬機(jī)規(guī)范中并沒(méi)有要求Java虛擬機(jī)垃圾收集,但是在沒(méi)有發(fā)明無(wú)限的內(nèi)存之前,大多數(shù)JVM實(shí)現(xiàn)都是有垃圾收集的。

Java堆是內(nèi)存管理中最大的一塊,所有的線程共享這一塊內(nèi)容,同時(shí)該部分也是垃圾收集器的主要區(qū)域。

虛擬機(jī)的垃圾回收機(jī)制是完善的,動(dòng)態(tài)內(nèi)存分配和回收是比較成熟的,在內(nèi)存管理機(jī)制中,大部分都不需要我們考慮內(nèi)存回收,只有Java堆和方法區(qū)需要我們考慮處理內(nèi)存問(wèn)題。一般的對(duì)于內(nèi)存回收首先就是判斷某一個(gè)部分是生存還是死亡,主要是通過(guò)下面二種算法:

其一是引用計(jì)數(shù)算法,本算法實(shí)現(xiàn)簡(jiǎn)單,判定的效率也是比較高的,很多的軟件都使用了該算法,但是主流的Java并沒(méi)有選擇該算法,核心的問(wèn)題是該算法難以處理對(duì)象之間相互調(diào)用的問(wèn)題。

其二是稱可達(dá)性分析算法,該算法核心思想是依靠判斷對(duì)象是否存活來(lái)實(shí)現(xiàn)的,本算法是通過(guò)一系列的GC ROOTS的對(duì)象作為起始點(diǎn),采用搜索的算法遍歷引用鏈,如果搜索過(guò)程中沒(méi)有發(fā)現(xiàn)該節(jié)點(diǎn),則認(rèn)為該節(jié)點(diǎn)是不可達(dá)的,即可回收的,在Java里面,一般可以使用該算法處理問(wèn)題。

2. 作用域

  • JVM 堆
    • 年輕代
    • 老年代
  • 元空間

3. 分類

當(dāng)前虛擬機(jī)的垃圾收集都采用分代收集算法,這種算法沒(méi)有什么新的思想,只是根據(jù)對(duì)象存活周期的不同將內(nèi)存分為幾塊。一般將java堆分為新生代和老年代,這樣我們就可以根據(jù)各個(gè)年代的特點(diǎn)選擇合適的垃圾收集算法。

4. 垃圾回收算法

4.1 標(biāo)記-復(fù)制算法

為了解決效率問(wèn)題,“復(fù)制”收集算法出現(xiàn)了。它可以將內(nèi)存分為大小相同的兩塊,每次使用其中的一塊。當(dāng)這一塊的內(nèi)存使用完后,就將還存活的對(duì)象復(fù)制到另一塊去,然后再把使用的空間一次清理掉。這樣就使每次的內(nèi)存回收都是對(duì)內(nèi)存區(qū)間的一半進(jìn)行回收

4.2 標(biāo)記-清除算法

算法分為“標(biāo)記”和“清除”階段:標(biāo)記存活的對(duì)象, 統(tǒng)一回收所有未被標(biāo)記的對(duì)象(一般選擇這種);也可以反過(guò)來(lái),標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象 。它是最基礎(chǔ)的收集算法,比較簡(jiǎn)單,但是會(huì)帶來(lái)兩個(gè)明顯的問(wèn)題:

  • 效率問(wèn)題 (如果需要標(biāo)記的對(duì)象太多,效率不高)
  • 空間問(wèn)題(標(biāo)記清除后會(huì)產(chǎn)生大量不連續(xù)的碎片)

4.3 標(biāo)記-整理算法

根據(jù)老年代的特點(diǎn)特出的一種標(biāo)記算法,標(biāo)記過(guò)程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象回收,而是讓所有存活的對(duì)象向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。

5. 垃圾收集器

5.1 Serial收集器(-XX:+UseSerialGC -XX:+UseSerialOldGC)

Serial(串行)收集器是最基本、歷史最悠久的垃圾收集器了。大家看名字就知道這個(gè)收集器是一個(gè)單線程收集器了。它的 “單線程” 的意義不僅僅意味著它只會(huì)使用一條垃圾收集線程去完成垃圾收集工作,更重要的是它在進(jìn)行垃圾收集工作的時(shí)候必須暫停其他所有的工作線程( “Stop The World” ),直到它收集結(jié)束。

新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法。

5.2 Parallel Scavenge收集器(-XX:+UseParallelGC(年輕代),-XX:+UseParallelOldGC(老年代))

Parallel收集器其實(shí)就是Serial收集器的多線程版本,除了使用多線程進(jìn)行垃圾收集外,其余行為(控制參數(shù)、收集算法、回收策略等等)和Serial收集器類似。默認(rèn)的收集線程數(shù)跟cpu核數(shù)相同,當(dāng)然也可以用參數(shù)(-XX:ParallelGCThreads)指定收集線程數(shù),但是一般不推薦修改。

Parallel Scavenge收集器關(guān)注點(diǎn)是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的關(guān)注點(diǎn)更多的是用戶線程的停頓時(shí)間(提高用戶體驗(yàn))。所謂吞吐量就是CPU中用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值。 Parallel Scavenge收集器提供了很多參數(shù)供用戶找到最合適的停頓時(shí)間或最大吞吐量,如果對(duì)于收集器運(yùn)作不太了解的話,可以選擇把內(nèi)存管理優(yōu)化交給虛擬機(jī)去完成也是一個(gè)不錯(cuò)的選擇。新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法。

Parallel Old收集器是Parallel Scavenge收集器的老年代版本。使用多線程和“標(biāo)記-整理”算法。在注重吞吐量以及CPU資源的場(chǎng)合,都可以優(yōu)先考慮 Parallel Scavenge收集器和Parallel Old收集器(JDK8默認(rèn)的新生代和老年代收集器)。

5.3 ParNew收集器(-XX:+UseParNewGC)

ParNew收集器其實(shí)跟Parallel收集器很類似,區(qū)別主要在于它可以和CMS收集器配合使用。

新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法。

它是許多運(yùn)行在Server模式下的虛擬機(jī)的首要選擇,除了Serial收集器外,只有它能與CMS收集器(真正意義上的并發(fā)收集器,后面會(huì)介紹到)配合工作。

5.4 CMS收集器(-XX:+UseConcMarkSweepGC(old))

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。它非常符合在注重用戶體驗(yàn)的應(yīng)用上使用,它是HotSpot虛擬機(jī)第一款真正意義上的并發(fā)收集器,它第一次實(shí)現(xiàn)了讓垃圾收集線程與用戶線程(基本上)同時(shí)工作。

從名字中的Mark Sweep這兩個(gè)詞可以看出,CMS收集器是一種 “標(biāo)記-清除”算法實(shí)現(xiàn)的,它的運(yùn)作過(guò)程相比于前面幾種垃圾收集器來(lái)說(shuō)更加復(fù)雜一些。整個(gè)過(guò)程分為四個(gè)步驟:

  • 初始標(biāo)記: 暫停所有的其他線程(STW),并記錄下gc roots直接能引用的對(duì)象,速度很快。
  • 并發(fā)標(biāo)記: 并發(fā)標(biāo)記階段就是從GC Roots的直接關(guān)聯(lián)對(duì)象開(kāi)始遍歷整個(gè)對(duì)象圖的過(guò)程, 這個(gè)過(guò)程耗時(shí)較長(zhǎng)但是不需要停頓用戶線程, 可以與垃圾收集線程一起并發(fā)運(yùn)行。因?yàn)橛脩舫绦蚶^續(xù)運(yùn)行,可能會(huì)有導(dǎo)致已經(jīng)標(biāo)記過(guò)的對(duì)象狀態(tài)發(fā)生改變。
  • 重新標(biāo)記: 重新標(biāo)記階段就是為了修正并發(fā)標(biāo)記期間因?yàn)橛脩舫绦蚶^續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,這個(gè)階段的停頓時(shí)間一般會(huì)比初始標(biāo)記階段的時(shí)間稍長(zhǎng),遠(yuǎn)遠(yuǎn)比并發(fā)標(biāo)記階段時(shí)間短。主要用到三色標(biāo)記里的增量更新算法(見(jiàn)下面詳解)做重新標(biāo)記。
  • 并發(fā)清理: 開(kāi)啟用戶線程,同時(shí)GC線程開(kāi)始對(duì)未標(biāo)記的區(qū)域做清掃。這個(gè)階段如果有新增對(duì)象會(huì)被標(biāo)記為黑色不做任何處理(見(jiàn)下面三色標(biāo)記算法詳解)。
  • 并發(fā)重置:重置本次GC過(guò)程中的標(biāo)記數(shù)據(jù)。

從它的名字就可以看出它是一款優(yōu)秀的垃圾收集器,主要優(yōu)點(diǎn):并發(fā)收集、低停頓。但是它有下面幾個(gè)

明顯的缺點(diǎn):

  • 對(duì)CPU資源敏感(會(huì)和服務(wù)搶資源);
  • 無(wú)法處理浮動(dòng)垃圾(在并發(fā)標(biāo)記和并發(fā)清理階段又產(chǎn)生垃圾,這種浮動(dòng)垃圾只能等到下一次gc再清理了);

它使用的回收算法-“標(biāo)記-清除”算法會(huì)導(dǎo)致收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生,當(dāng)然通過(guò)參數(shù)-XX:+UseCMSCompactAtFullCollection可以讓jvm在執(zhí)行完標(biāo)記清除后再做整理執(zhí)行過(guò)程中的不確定性,會(huì)存在上一次垃圾回收還沒(méi)執(zhí)行完,然后垃圾回收又被觸發(fā)的情況,特別是在并發(fā)標(biāo)記和并發(fā)清理階段會(huì)出現(xiàn),一邊回收,系統(tǒng)一邊運(yùn)行,也許沒(méi)回收完就再次觸發(fā)full gc,也就是"concurrent mode failure",此時(shí)會(huì)進(jìn)入stop the world,用serial old垃圾收集器來(lái)回收

5.5 CMS的相關(guān)核心參數(shù)

-XX:+UseConcMarkSweepGC:?jiǎn)⒂胏ms
-XX:ConcGCThreads:并發(fā)的GC線程數(shù)
-XX:+UseCMSCompactAtFullCollection:FullGC之后做壓縮整理(減少碎片)
-XX:CMSFullGCsBeforeCompaction:多少次FullGC之后壓縮一次,默認(rèn)是0,代表每次FullGC后都會(huì)壓縮一次 
-XX:CMSInitiatingOccupancyFraction: 當(dāng)老年代使用達(dá)到該比例時(shí)會(huì)觸發(fā)FullGC(默認(rèn)是92,這是百分比)
-XX:+UseCMSInitiatingOccupancyOnly:只使用設(shè)定的回收閾值(-XX:CMSInitiatingOccupancyFraction設(shè)定的值),如果不指定,JVM僅在第一次使用設(shè)定值,后續(xù)則會(huì)自動(dòng)調(diào)整
-XX:+CMSScavengeBeforeRemark:在CMS GC前啟動(dòng)一次minor gc,降低CMS GC標(biāo)記階段(也會(huì)對(duì)年輕代一起做標(biāo)記,如果在minor gc就干掉了很多對(duì)垃圾對(duì)象,標(biāo)記階段就會(huì)減少一些標(biāo)記時(shí)間)時(shí)的開(kāi)銷,一般CMS的GC耗時(shí) 80%都在標(biāo)記階段
-XX:+CMSParallellnitialMarkEnabled:表示在初始標(biāo)記的時(shí)候多線程執(zhí)行,縮短STW
-XX:+CMSParallelRemarkEnabled:在重新標(biāo)記的時(shí)候多線程執(zhí)行,縮短STW;

6. 垃圾收集底層算法實(shí)現(xiàn)

  • 三色標(biāo)記

在并發(fā)標(biāo)記的過(guò)程中,因?yàn)闃?biāo)記期間應(yīng)用線程還在繼續(xù)跑,對(duì)象間的引用可能發(fā)生變化,多標(biāo)和漏標(biāo)的情況就有可能發(fā)生。

這里我們引入“三色標(biāo)記”來(lái)給大家解釋下,把Gcroots可達(dá)性分析遍歷對(duì)象過(guò)程中遇到的對(duì)象, 按照“是否訪問(wèn)過(guò)”這個(gè)條件標(biāo)記成以下三種顏色:

  • 黑色: 表示對(duì)象已經(jīng)被垃圾收集器訪問(wèn)過(guò), 且這個(gè)對(duì)象的所有引用都已經(jīng)掃描過(guò)。 黑色的對(duì)象代表已經(jīng)掃描過(guò), 它是安全存活的, 如果有其他對(duì)象引用指向了黑色對(duì)象, 無(wú)須重新掃描一遍。 黑色對(duì)象不可能直接(不經(jīng)過(guò)灰色對(duì)象) 指向某個(gè)白色對(duì)象。
  • 灰色: 表示對(duì)象已經(jīng)被垃圾收集器訪問(wèn)過(guò), 但這個(gè)對(duì)象上至少存在一個(gè)引用還沒(méi)有被掃描過(guò)。
  • 白色: 表示對(duì)象尚未被垃圾收集器訪問(wèn)過(guò)。 顯然在可達(dá)性分析剛剛開(kāi)始的階段, 所有的對(duì)象都是白色的, 若在分析結(jié)束的階段, 仍然是白色的對(duì)象, 即代表不可達(dá)。

7 .總結(jié)

Jvm優(yōu)化主要是防止fullgc,縮短STW時(shí)間,杜絕OOM出現(xiàn),而實(shí)現(xiàn)這一手段主要是依賴?yán)厥諜C(jī)制,具體來(lái)說(shuō)就是垃圾回收器,而垃圾回收器又分了好多種,單線程,并發(fā),回收算法的差異性等等,所以要做到深度優(yōu)化,必須理解其底層機(jī)制。

相關(guān)文章

  • MyBatis-Plus中實(shí)現(xiàn)自定義復(fù)雜排序邏輯的詳細(xì)步驟

    MyBatis-Plus中實(shí)現(xiàn)自定義復(fù)雜排序邏輯的詳細(xì)步驟

    這篇文章主要介紹了MyBatis-Plus中實(shí)現(xiàn)自定義復(fù)雜排序邏輯,通過(guò)使用MyBatis-Plus的QueryWrapper和SQL原始片段,我們可以靈活地實(shí)現(xiàn)復(fù)雜的數(shù)據(jù)排序邏輯,這種方法尤其適用于需要對(duì)數(shù)據(jù)進(jìn)行特定規(guī)則排序的場(chǎng)景,需要的朋友可以參考下
    2024-07-07
  • springboot如何通過(guò)SSH連接遠(yuǎn)程服務(wù)器

    springboot如何通過(guò)SSH連接遠(yuǎn)程服務(wù)器

    這篇文章主要介紹了springboot如何通過(guò)SSH連接遠(yuǎn)程服務(wù)器問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 使用spring stream發(fā)送消息代碼實(shí)例

    使用spring stream發(fā)送消息代碼實(shí)例

    這篇文章主要介紹了使用spring stream發(fā)送消息代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • SpringBoot JavaMailSender發(fā)送郵件功能

    SpringBoot JavaMailSender發(fā)送郵件功能

    這篇文章主要為大家詳細(xì)介紹了SpringBoot JavaMailSender發(fā)送郵件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • SpringBoot?@InitBinder注解綁定請(qǐng)求參數(shù)的過(guò)程詳解

    SpringBoot?@InitBinder注解綁定請(qǐng)求參數(shù)的過(guò)程詳解

    這篇文章主要介紹了SpringBoot?@InitBinder注解綁定請(qǐng)求參數(shù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Java程序執(zhí)行過(guò)程及內(nèi)存機(jī)制詳解

    Java程序執(zhí)行過(guò)程及內(nèi)存機(jī)制詳解

    本講將介紹Java代碼是如何一步步運(yùn)行起來(lái)的,還會(huì)介紹Java程序所占用的內(nèi)存是被如何管理的:堆、棧和方法區(qū)都各自負(fù)責(zé)存儲(chǔ)哪些內(nèi)容,感興趣的朋友跟隨小編一起看看吧
    2020-12-12
  • 在SpringBoot: SpringBoot里面創(chuàng)建導(dǎo)出Excel的接口教程

    在SpringBoot: SpringBoot里面創(chuàng)建導(dǎo)出Excel的接口教程

    這篇文章主要介紹了在SpringBoot: SpringBoot里面創(chuàng)建導(dǎo)出Excel的接口教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • 如何將JSP/Servlet項(xiàng)目轉(zhuǎn)換為Spring Boot項(xiàng)目

    如何將JSP/Servlet項(xiàng)目轉(zhuǎn)換為Spring Boot項(xiàng)目

    這篇文章主要介紹了如何將JSP/Servlet項(xiàng)目轉(zhuǎn)換為Spring Boot項(xiàng)目,幫助大家更好的利用springboot進(jìn)行網(wǎng)絡(luò)編程,感興趣的朋友可以了解下
    2020-10-10
  • Java關(guān)鍵詞final示例解讀

    Java關(guān)鍵詞final示例解讀

    這篇文章主要介紹了Java關(guān)鍵詞final解讀,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • Java如何實(shí)現(xiàn)判斷并輸出文件大小

    Java如何實(shí)現(xiàn)判斷并輸出文件大小

    這篇文章主要介紹了Java如何實(shí)現(xiàn)判斷并輸出文件大小問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04

最新評(píng)論