最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM中的GC初識

 更新時(shí)間:2022年05月23日 16:34:27   作者:雨田說碼  
GC(Garbage Collection)稱之為垃圾回收,是對內(nèi)存中的垃圾對象,采用一定的算法進(jìn)行內(nèi)存回收的一個(gè)動(dòng)作,這篇文章主要介紹了JVM中的GC初識,需要的朋友可以參考下

GC簡介

何為GC

GC(Garbage Collection)稱之為垃圾回收,是對內(nèi)存中的垃圾對象,采用一定的算法進(jìn)行內(nèi)存回收的一個(gè)動(dòng)作。比方說,java中的垃圾回收會(huì)對內(nèi)存中的對象進(jìn)行遍歷,對存活的對象進(jìn)行標(biāo)記,其未標(biāo)記對象可認(rèn)為是垃圾對象,然后基于特定算法進(jìn)行回收。

為何要學(xué)習(xí)GC

深入理解GC的工作機(jī)制,可以幫你寫出更好的Java應(yīng)用,提高開發(fā)效率,同時(shí)也是進(jìn)軍大規(guī)模應(yīng)用開發(fā)的一個(gè)前提。

GC垃圾對象判定

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

這個(gè)算法是給每一個(gè)對象設(shè)置一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用這個(gè)對象的時(shí)候,計(jì)數(shù)器就加 1,與之相反,每當(dāng)引用失效的時(shí)候就減 1。也就是以計(jì)數(shù)來判斷對象是否為垃圾。當(dāng)某個(gè)對象的引用計(jì)數(shù)器的值為0時(shí),表示這個(gè)對象不會(huì)在被實(shí)用,JVM中的GC被觸發(fā)時(shí),可回收這個(gè)對象。如圖所示:

其中:

  • 綠色云朵是內(nèi)存中的根對象,表示程序中正在使用的對象。
  • 藍(lán)色圓圈是內(nèi)存中的活動(dòng)對象,其中的數(shù)字表示其引用計(jì)數(shù)。
  • 灰色圓圈是內(nèi)存中沒有活動(dòng)對象引用的對象,表示非活動(dòng)對象。

對于引用計(jì)數(shù)法,實(shí)現(xiàn)簡單,垃圾對應(yīng)也便于識別。但也有一些缺陷,我們每個(gè)對象都需要有一個(gè)單獨(dú)的對象引用計(jì)數(shù)器,這個(gè)計(jì)數(shù)器的值還要經(jīng)常更新,還有就是有一個(gè)最嚴(yán)重的循環(huán)引用問題,如圖所示:

其中紅色對象實(shí)際上是應(yīng)用程序不使用的垃圾。但由于引用計(jì)數(shù)的限制,仍然存在內(nèi)存泄漏。當(dāng)然也有一些辦法來應(yīng)來對這種情況, 例如 “弱引用”(‘weak’ references)或者使用其它的算法來排查循環(huán)引用等。

可達(dá)性分析法

這個(gè)算法的核心思路就是通過一系列的“GC Roots”對象作為起始點(diǎn),從這些對象開始往下搜索,搜索所經(jīng)過的路徑稱之為“引用鏈”。當(dāng)一個(gè)對象到 GC Roots 沒有任何引用鏈相連的時(shí)候,證明此對象是可以被回收的。否則,證明這個(gè)對象有用,不是垃圾。如圖所示:

在GC遍歷(traverses)內(nèi)存中整體的對象關(guān)系圖(object graph)時(shí),首先要確定根對象,那什么樣的對象可作為根對象呢?GC規(guī)范中指出根對象可以是:

1)Java 虛擬機(jī)棧中的引用對象;
2)本地方法棧中 JNI(既一般說的 Native 方法)引用的對象;
3)方法區(qū)中類靜態(tài)常量的引用對象;
4)方法區(qū)中常量的引用對象。

當(dāng)確定了根對象以后,進(jìn)而從根對象開始進(jìn)行依賴查找,所有可訪問到的對象都認(rèn)為是存活對象,然后進(jìn)行標(biāo)記(mark)。

說明:標(biāo)記可達(dá)對象需要暫停所有應(yīng)用線程, 以確定對象的引用關(guān)系。其暫停的時(shí)間, 與堆內(nèi)存大小、對象的總數(shù)沒有直接關(guān)系, 而是由存活對象(alive objects)的數(shù)量來決定。

常見GC算法分析

標(biāo)記清除

標(biāo)記清除(Mark-Sweep)算法分為“標(biāo)記”和“清除”階段,它首先會(huì)標(biāo)記出內(nèi)存中所有不需要回收的對象,然后從內(nèi)存中清除所有未標(biāo)記的對象。 如圖所示:

標(biāo)記清除算法的的優(yōu)點(diǎn)是簡單直接,缺點(diǎn)是效率低,并且可能會(huì)產(chǎn)生大量不連續(xù)的碎片。說它效率低是因?yàn)闃?biāo)記和清除兩個(gè)過程都需要掃描內(nèi)存空間(第一次:標(biāo)記存活對象,第二次:清除沒有標(biāo)記的對象)。還有就是,清除后產(chǎn)生的大量不連續(xù)的內(nèi)存碎片空間,無法滿足較大對象的存儲需求,這樣就可能會(huì)再次觸發(fā)垃圾回收。所以此垃圾回收算法,應(yīng)該適合對象存活率較高的的內(nèi)存區(qū)域(比方說JVM中的老年代)。

標(biāo)記復(fù)制

標(biāo)記復(fù)制(Mark-Copy)算法是將內(nèi)存分為大小相同的兩塊,當(dāng)這一塊使用完了,就把當(dāng)前存活的對象復(fù)制到另一塊,然后一次性清空當(dāng)前區(qū)塊。如圖所示:

“標(biāo)記-復(fù)制”算法的缺點(diǎn)顯而易見,就是內(nèi)存空間利用率低,適用于那些對象生命周期短、回收頻率高的內(nèi)存區(qū)域(比方說JVM中的年輕代)。

標(biāo)記整理

標(biāo)記整理清除(Mark-Sweep-Compact)算法結(jié)合了“標(biāo)記-清除”和“復(fù)制”兩個(gè)算法的優(yōu)點(diǎn)。第一階段從根節(jié)點(diǎn)開始標(biāo)記所有被引用對象,第二階段遍歷整個(gè)堆,把存活對象“壓縮”復(fù)制到堆的其中一塊空間中,按順序排放。第三階段清理掉存活邊界以外的全部內(nèi)存空間。如圖所示:

系統(tǒng)GC時(shí)每次執(zhí)行清除(sweeping)操作, JVM 都必須保證“不可達(dá)對象“占用的內(nèi)存能被回收然后重用。內(nèi)存是被回收了,但這有可能會(huì)產(chǎn)生大量的內(nèi)存碎片(類似于磁盤碎片), 進(jìn)而引發(fā)兩個(gè)問題:

  • 對象創(chuàng)建時(shí),執(zhí)行寫入操作越來越耗時(shí), 因?yàn)閷ふ乙粔K足夠大的空閑內(nèi)存會(huì)變得更加麻煩。
  • 對象創(chuàng)建時(shí), JVM需要在連續(xù)的內(nèi)存塊中為對象分配內(nèi)存。如果碎片問題很嚴(yán)重, 直至沒有空閑片段能存放新創(chuàng)建的對象,就會(huì)發(fā)生內(nèi)存分配錯(cuò)誤(allocation error)。

為了解決碎片問題,JVM在啟動(dòng)GC執(zhí)行垃圾收集的過程中, 不僅僅是標(biāo)記和清除, 還需要執(zhí)行 “內(nèi)存碎片整理”。這個(gè)過程會(huì)讓所有可達(dá)對象(reachable objects)進(jìn)行依次移動(dòng),進(jìn)而可以消除(或減少)內(nèi)存碎片,并為新對象提供更大并且連續(xù)的內(nèi)存空間。

標(biāo)記整理算法避免了“標(biāo)記-清除”的碎片問題,同時(shí)也避免了“復(fù)制”算法的空間問題,由于需要向一側(cè)移動(dòng)等一系列操作,其效率相對低一些,但對內(nèi)存空間管理上十分優(yōu)異。適用于那些生命周期長、回收頻率低,但注重回收一次內(nèi)存空間得到足夠釋放的場景。

分代回收

我們知道垃圾收集要停止整個(gè)應(yīng)用程序的運(yùn)行,那么假如這個(gè)收集過程需要的時(shí)間很長,就會(huì)對應(yīng)用程序產(chǎn)生很大性能問題,如何解決這個(gè)問題呢?通過實(shí)驗(yàn)發(fā)現(xiàn)內(nèi)存中的對象通??梢詫⑵浞譃閮纱箢悾?/p>

  • 存活時(shí)間較短(這樣的對象比較多)。
  • 存活時(shí)間較長(這樣的對象比較少)。

基于對如上問題的分析,科學(xué)家提出了分代回收思路,將VM中內(nèi)存分為年輕代(Young Generation)和老年代(Old Generation-老年代有時(shí)候也稱為年老區(qū)(Tenured)。例如:

Young區(qū)存儲的就是那些生命周期短,使用一兩次就不再使用的對象,回收一次基本上該區(qū)域十之有八的對象全部被回收清理掉,因此Young區(qū)采用的垃圾回收算法也就是“標(biāo)記-復(fù)制”算法。Old區(qū)存儲的是那些生命周期長,經(jīng)過多次回收后仍然存活的對象,就把它們放到Old區(qū)中,Old區(qū)一般不去判斷這些對象的可達(dá)性,直到Old區(qū)不夠用為止,再進(jìn)行一次統(tǒng)一的回收,釋放出足夠的連續(xù)的內(nèi)存空間。所以我們選擇“標(biāo)記-清除”或“標(biāo)記-整理”算法進(jìn)行垃圾收集。

在分代回收過程中,垃圾收集事件(Garbage Collection events)通常分為:

  • Minor GC (小型GC):年輕代GC事件,(新對象)分配頻率越高, Minor GC 的頻率就越高。
  • Major GC (大型GC): 老年代GC事件。
  • Full GC (完全GC):整個(gè)堆的GC事件。

說明:一般情況下可以將Major GC與Full GC看成是同一種GC。

章節(jié)面試分析

1)何為GC?
2)為什么要GC?
3)如何判定內(nèi)存中的對象是否為垃圾對象?
4)常用垃圾回收算法有哪些?

到此這篇關(guān)于JVM中的GC初識的文章就介紹到這了,更多相關(guān)初識JVM中的GC內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud:feign對象傳參和普通傳參及遇到的坑解決

    SpringCloud:feign對象傳參和普通傳參及遇到的坑解決

    這篇文章主要介紹了SpringCloud:feign對象傳參和普通傳參及遇到的坑解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 使用Jitpack發(fā)布開源Java庫的詳細(xì)流程

    使用Jitpack發(fā)布開源Java庫的詳細(xì)流程

    這篇文章主要介紹了使用Jitpack發(fā)布開源Java庫的詳細(xì)流程,本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • 詳解最簡單易懂的Spring Security 身份認(rèn)證流程講解

    詳解最簡單易懂的Spring Security 身份認(rèn)證流程講解

    這篇文章主要介紹了詳解最簡單易懂的Spring Security 身份認(rèn)證流程講解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • SpringBoot的Security和OAuth2的使用示例小結(jié)

    SpringBoot的Security和OAuth2的使用示例小結(jié)

    這篇文章主要介紹了SpringBoot的Security和OAuth2的使用,本文通過示例圖文相結(jié)合給大家講解的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • java 兩個(gè)數(shù)組合并的幾種方法

    java 兩個(gè)數(shù)組合并的幾種方法

    本篇文章主要介紹了java 兩個(gè)數(shù)組合并的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • Nacos配置中心設(shè)計(jì)原理分析

    Nacos配置中心設(shè)計(jì)原理分析

    今天分享一下Nacos配置變更的相關(guān)知識點(diǎn),現(xiàn)在使用Java生態(tài)如果使用微服務(wù),如果部署在K8s上,那么可能會(huì)使用ConfigMap來存儲配置文件,如果沒有使用K8s,那么基本上都使用Nacos來做配置中心,所以有必要了解一下Nacos的配置的知識點(diǎn),本文只是對其中的部分實(shí)現(xiàn)原理進(jìn)行分析
    2023-10-10
  • Java Grpc實(shí)例創(chuàng)建負(fù)載均衡詳解

    Java Grpc實(shí)例創(chuàng)建負(fù)載均衡詳解

    這篇文章主要介紹了Java Grpc實(shí)例創(chuàng)建負(fù)載均衡詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 關(guān)于連接池詳解(HikariCP、Druid)

    關(guān)于連接池詳解(HikariCP、Druid)

    這篇文章主要介紹了關(guān)于連接池詳解(HikariCP、Druid),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java并發(fā)編程示例(二):獲取和設(shè)置線程信息

    Java并發(fā)編程示例(二):獲取和設(shè)置線程信息

    這篇文章主要介紹了Java并發(fā)編程示例(二):獲取和設(shè)置線程信息,本文是系列文章的第二篇,本文著重講解Thread類的幾個(gè)重要屬性,需要的朋友可以參考下
    2014-12-12
  • SpringBoot項(xiàng)目配置文件注釋亂碼的問題解決方案

    SpringBoot項(xiàng)目配置文件注釋亂碼的問題解決方案

    這篇文章主要介紹了SpringBoot 項(xiàng)目配置文件注釋亂碼的問題解決方案,文中通過圖文結(jié)合的方式給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-07-07

最新評論

英德市| 富顺县| 敦化市| 井冈山市| 平乡县| 合水县| 佛学| 宿州市| 内丘县| 鹰潭市| 永宁县| 青海省| 邓州市| 桂平市| 佛学| 个旧市| 沂南县| 淮滨县| 乡宁县| 河西区| 南充市| 宜都市| 西城区| 全南县| 仪征市| 岳普湖县| 喀喇沁旗| 甘孜县| 溧水县| 聂荣县| 天台县| 伊通| 岐山县| 定南县| 韶关市| 阿尔山市| 龙州县| 新化县| 平遥县| 汝州市| 新营市|