亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JVM之內(nèi)存分配和回收機制

 更新時間:2023年05月01日 13:18:50   作者:吃貓的大魚  
本篇主要介紹JVM內(nèi)存分配和回收策略,內(nèi)容主要節(jié)選自《深入理解java虛擬機》,需要的朋友可以參考下

前言

本篇主要介紹JVM內(nèi)存分配和回收策略,內(nèi)容主要節(jié)選自《深入理解java虛擬機》。

一、內(nèi)存分配策略

1. 堆內(nèi)存模型

在這里插入圖片描述

組成:

  • 新生代 默認占堆空間的三分之一,由于在新生代對象大多都是朝生夕死,則采用的是復(fù)制算法,在復(fù)制的期間會有頻繁的Minor GC。
  • 老年代 默認占堆空間的三分之二,老年代對象大多都是長期存活的,則采用的是標(biāo)記算法,老年代的Major GC開銷非常大。
  • Eden 新生代分為2個區(qū) Eden和Survivor區(qū) 其中Eden區(qū)默認占新生代十分之八的空間,對象優(yōu)先進入Eden區(qū)。
  • Survivor 當(dāng)Eden區(qū)內(nèi)存滿了之后會進行一次Minor GC存活對象會進入Survivor區(qū),默認占新生代十分之二空間, 其中它又均分為From區(qū)和To區(qū),在Survivor區(qū)的對象每熬過一次從From區(qū)到TO區(qū)則年齡+1。

大多情況下,對象在新生代Eden區(qū)中分配。當(dāng)Eden沒有足夠的空間分配對象時虛擬機會發(fā)起一次Minor GC。

2.2 大對象直接到老年代

大對象即需要大量連續(xù)內(nèi)存空間的對象(例如很長的字符串及數(shù)組)。虛擬機提供了一個-XX:PretenureSizeThreshoId參數(shù),令大于這個設(shè)置值的對象直接在老年代分配,這樣做的目的是避免在Eden區(qū)及兩個區(qū)之間發(fā)生大量的內(nèi)存復(fù)制。注意PretenureSizeThreshoId參數(shù)只對Serial和ParNew兩款收集器有效。

2.3 動態(tài)年齡判斷

為了能更好地適應(yīng)不同程序的內(nèi)存狀況,虛擬機并不是永遠地要求對象的年齡必須達到了MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進人老年代,無須等到MaxTenuringThreshoId中要求的年齡。

2.4 內(nèi)存擔(dān)保機制

在發(fā)生Minor GC之前,虛擬機會先檢查Survivor空間是否夠用,如果夠用則直接進行Minor GC。否則進行檢查老年代最大連續(xù)可用空間是否大于新生代的總和,假如大于,那么這個時候發(fā)生Minor GC是安全的。假如不大于,那么需要判斷HandlePromotionFailure設(shè)置是否允許擔(dān)保失敗。假如允許,則繼續(xù)判定老年代最大可用的連續(xù)空間是否大于平均晉升到老年代對象的平均值,如果大于,這個時候可以發(fā)生Minor GC ,如果小于或者設(shè)置HandlePromotionFailure不允許擔(dān)保失敗,則需要做一次Full GC。通常會把HandlePromotionFailure開關(guān)打開,以減少Full GC。

2.5 長期存活對象

虛擬機給每個對象定義了一個對象年齡(Age)計數(shù)器(存在于對象頭中)。如果對象在Eden出生并經(jīng)過第一次MinorGC后仍然存活,并且能被Survivor容納的話,將被移動到Survwor空間中,并且對象年齡設(shè)為1。對象在Survivor區(qū)中每“熬過”一次MinorGC,年齡就增加1歲,當(dāng)它的年齡增加到一定程度(默認為15歲),就將會被晉升到老年代中。對象晉升老年代的年齡閾值,可以通過參數(shù)-XX:MaxTenuringThreshoId設(shè)置。

二、對象存活

判斷對象存活一般有兩種方式: 引用計數(shù)算法和可達性分析算法。

1.引用計數(shù)算法

原理:

  1. 引用計數(shù)算法(Reference Counting)比較簡單,對每個對象保存一個整型的引用計數(shù)器屬性。用于記錄對象被引用的情況。
  2. 對于一個對象A,只要有任何一個對象引用了A,則A的引用計數(shù)器就加1;當(dāng)引用失效時,引用計數(shù)器就減1。只要對象A的引用計數(shù)器的值為0,即表示對象A不可能再被使用,可進行回收。

優(yōu)點:

  1. 實現(xiàn)簡單,垃圾對象便于辨識;
  2. 判定效率高,回收沒有延遲性。

缺點:

  1. 它需要單獨的字段存儲計數(shù)器,這樣的做法增加了存儲空間的開銷。
  2. 每次復(fù)制都需要更新計數(shù)器,伴隨著加法和減法操作,這增加了時間開銷。
  3. 引用計數(shù)器有一個嚴重的問題,即無法處理循環(huán)引用的情況。這是一條致命缺陷,導(dǎo)致在Java的垃圾回收器中沒有使用這類算法。

2.可達性分析算法

定義:相對于引用計數(shù)算法而言,可達性分析算法不僅同樣具備實現(xiàn)簡單和執(zhí)行高效等特點,更重要的是該算法可以有效地解決在引用計數(shù)算法中循環(huán)引用的問題,防止內(nèi)存泄漏的發(fā)生。

原理:

  1. 可達性分析算法是以根對象集合(GCRoots)為起始點,按照從上至下的方式搜索被根對象集合所連接的目標(biāo)對象是否可達。
  2. 使用可達性分析算法后,內(nèi)存中的存活對象都會被根對象集合直接或間接連接著,搜索所走過的路徑稱為引用鏈(Reference Chain)。
  3. 如果目標(biāo)對象沒有任何引用鏈相連,則是不可達的,就意味著該對象己經(jīng)死亡,可以標(biāo)記為垃圾對象。
  4. 在可達性分析算法中,只有能夠被根對象集合直接或者間接連接的對象才是存活對象。


在這里插入圖片描述

GC ROOT 對象:

  • 虛擬機棧中引用的對象;
    比如:各個線程被調(diào)用的方法中使用到的參數(shù)、局部變量等。
  • 本地方法棧內(nèi) JNI(通常說的本地方法)引用的對象;
  • 方法區(qū)中類靜態(tài)屬性引用的對象;
    比如:Java類的引用類型靜態(tài)變量
  • 方法區(qū)中常量引用的對象;
    比如:字符串常量池(string Table)里的引用
  • 所有被同步鎖 synchronized 持有的對象;
  • Java虛擬機內(nèi)部的引用。
    基本數(shù)據(jù)類型對應(yīng)的 Class 對象,一些常駐的異常對象(如:NullPointerException、OutOfMemoryError),系統(tǒng)類加載器。

3.再談引用

  • 強引用:強引用在代碼中普遍存在,例如Object obj=new Object() 這類的引用。只要強引用存在,垃圾回收器永遠不會回收掉被引用的對象。
  • 軟引用:軟引用來描述一些還有用但并非必須的對象,在系統(tǒng)要發(fā)生內(nèi)存溢出之前,將會把這些對象列入回收范圍之中進行第二次回收,如果第二次回收還沒有足夠的內(nèi)存,才會拋出內(nèi)存溢出異常。
  • 弱引用:弱引用也是用來描述必須對象的,但是它的強度比軟引用更弱,被弱引用關(guān)聯(lián)的對象只能生存到下一次垃圾回收發(fā)生之前。當(dāng)垃圾回收器工作時,無論內(nèi)存是否足夠,都回收掉只被弱引用關(guān)聯(lián)的對象。
  • 虛引用:它是最弱的一種引用關(guān)系。它無法通過虛引用來取得一個對象實例。唯一目的就是能在這個對象被回收之前會收到一個系統(tǒng)通知。

三、內(nèi)存回收

1.堆內(nèi)存回收

是JVM所管理內(nèi)存最大的一塊,也是gc回收的主要區(qū)域。

1.1 哪些對象能回收?

堆內(nèi)存中對象存活是使用可達性分析算法來判斷,其中非存活對象由GC回收掉。這個就是虛擬機需要回收堆的對象。

1.2 如何回收?

  1. Minor GC:新生代收集,目標(biāo)只是新生代的垃圾收集;
  2. Major GC:老年代收集,目標(biāo)是老年代的垃圾收集(具體說只有CMS會有單獨收集老年代的行為);
  3. Full GC:收集整個java堆和方法區(qū)的垃圾收集。這里補充說明一下雖然網(wǎng)上很多說什么Full GC就是Major GC,在這里我要重申一下并不是,具體看書上描述如下:


在這里插入圖片描述

Mixed GC:收集整個新生代以及部分老年代的垃圾收集,僅G1支持。(類似于Full GC)

1.3 什么時候回收?

Minor GC觸發(fā)條件:

  1. Eden區(qū)域滿了,會觸發(fā)Minor GC;
  2. 新生對象需要分配到新生代的Eden,當(dāng)Eden區(qū)的內(nèi)存不夠時需要進行MinorGC。

Major GC觸發(fā)條件:

  1. 老年代區(qū)域設(shè)置的閾值空間滿了,會觸發(fā)Major GC;
  2. 新對象需要分配到老年代,此時老年代設(shè)置閾值可用空間不足時觸發(fā)Major GC。

Full GC觸發(fā)條件:

  • 內(nèi)存擔(dān)保機制 ,Survivor空間不足時,判斷是否允許擔(dān)保失敗,如果不允許則進行Full GC。如果允許,并且每次晉升到老年代的對象平均大小>老年代最大可用連續(xù)內(nèi)存空間,也會進行Full GC;
  • MinorGC后存活的對象超過了老年代剩余空間;
  • 方法區(qū)內(nèi)存不足時;
  • 程序中調(diào)用了System.gc()方法,可用通過-XX:+ DisableExplicitGC來禁止調(diào)用System.gc;
  • CMS GC異常,CMS運行期間預(yù)留的內(nèi)存無法滿足程序需要,就會出現(xiàn)一次“Concurrent Mode Failure”失敗,會觸發(fā)Full GC。

2.方法區(qū)回收

方法區(qū)主要回收廢棄的常量池和不再使用類型,但這個2類對象存活的判斷還不一樣。

2.1 常量池

同堆的對象存活類似-可達性分析法,具體請參考之前的可達性分析法。

2.2 類型數(shù)據(jù)

  • 該類索引的實例都已經(jīng)被回收;
  • 加載該類的類加載器已經(jīng)被回收;
  • 該類對應(yīng)的java.lang.class對象沒有任何地方被引用。

以上都是我簡單總結(jié),以下是書上關(guān)于方法區(qū)回收描述的內(nèi)容:


在這里插入圖片描述

其實從書上就可以看出來,關(guān)于方法區(qū)OOM問題大都是在程序中是有大量使用反射、動態(tài)代理、CGLIB等框架,如果在實際開發(fā)中遇到關(guān)于可以從以上幾個維度來定位問題。

總結(jié)

本篇所有理論知識都是摘抄于《深入理解java虛擬機》,有部分是自己簡單總結(jié),JVM內(nèi)存分配和回收是我們在分析JVM調(diào)優(yōu)和相關(guān)問題的基石,建議看完我本篇的去多看幾遍《深入理解java虛擬機》。

相關(guān)文章

  • Java 獲取兩個List的交集和差集,以及應(yīng)用場景操作

    Java 獲取兩個List的交集和差集,以及應(yīng)用場景操作

    這篇文章主要介紹了Java 獲取兩個List的交集和差集,以及應(yīng)用場景操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 如何獲取所有spring管理的bean

    如何獲取所有spring管理的bean

    這篇文章主要介紹了如何獲取所有spring管理的bean,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Sentinel中三種流控模式的使用詳解

    Sentinel中三種流控模式的使用詳解

    這篇文章主要為大家詳細介紹了Sentinel中三種流控模式(預(yù)熱模式,排隊等待模式和熱點規(guī)則)的使用,文中的示例代碼講解詳細,感興趣的可以了解下
    2023-08-08
  • Java中HashMap的put過程詳解

    Java中HashMap的put過程詳解

    這篇文章主要介紹了Java中HashMap的put過程詳解,HashMap有4個構(gòu)造器,其他構(gòu)造器如果用戶沒有傳入initialCapacity?和loadFactor這兩個參數(shù),會使用默認值一般如果new?HashMap()不傳值,需要的朋友可以參考下
    2023-07-07
  • Java8新特性之方法引用的實踐指南

    Java8新特性之方法引用的實踐指南

    這篇文章主要給大家介紹了關(guān)于Java8新特性之方法引用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 淺談Storm在zookeeper上的目錄結(jié)構(gòu)

    淺談Storm在zookeeper上的目錄結(jié)構(gòu)

    這篇文章主要介紹了淺談Storm在zookeeper上的目錄結(jié)構(gòu)的相關(guān)內(nèi)容,涉及storm使用zookeeper的操作以及詳細結(jié)構(gòu)圖,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • jvm類加載器基礎(chǔ)解析

    jvm類加載器基礎(chǔ)解析

    這篇文章主要介紹了jvm類加載器基礎(chǔ)解析,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • Spring Initializr中生成的mvnw有什么用

    Spring Initializr中生成的mvnw有什么用

    這篇文章主要介紹了Spring Initializr中生成的mvnw有什么用,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Java Date時間類型的操作實現(xiàn)

    Java Date時間類型的操作實現(xiàn)

    本文主要介紹Java Date 日期類型,以及Calendar的怎么獲取時間,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • Spring 整合 MyBatis的實現(xiàn)步驟

    Spring 整合 MyBatis的實現(xiàn)步驟

    SpringMVC 本來就是 Spring 框架的一部分,這兩者無須再做整合,所以 SSM 整合的關(guān)鍵就是Spring對MyBatis的整合,三大框架整合完成后,將以 Spring 為核心,調(diào)用有關(guān)資源,高效運作,這篇文章主要介紹了 Spring 整合 MyBatis的實現(xiàn)步驟,需要的朋友可以參考下
    2023-02-02

最新評論