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

JVM垃圾回收算法的概念與分析

 更新時間:2019年12月17日 08:30:57   作者:架構(gòu)文摘  
這篇文章主要給大家介紹了關(guān)于JVM垃圾回收算法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用JVM具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

前言

在JVM內(nèi)存模型中會將堆內(nèi)存劃分新生代、老年代兩個區(qū)域,兩塊區(qū)域的主要區(qū)別在于新生代存放存活時間較短的對象,老年代存放存活時間較久的對象,除了存活時間不同外,還有垃圾回收策略的不同,在JVM中中有以下回收算法:

  • 標記清除
  • 標記整理
  • 復(fù)制算法
  • 分代收集算法

有了垃圾回收算法,那JVM是如果確定對象是垃圾對象的呢?判斷對象是否存活JVM也會有幾套自己判斷算法了:

  • 引用記數(shù)
  • 可達性分析

有了垃圾回收和判斷對象存在這兩個概念后,再來逐步分析它們。

JVM是如何判斷對象是否存活的?

要是讓開發(fā)人員來判斷一個對象是否有用是很簡單的,簡單的說就是:對象沒有任何引用就認為該對象可以被回收了。假設(shè)有如下程序代碼:

public class App {

 public static void main(){
  checkFile("/");
 }

 public static boolean checkFile(String path ){
  File file = new File(path);
  return file.exists();
 }
}

程序執(zhí)行起來在調(diào)用checkFile的時候JVM圖大概像這樣:

到checkFile方法執(zhí)行完成之后,它里面的局部變量file就會隨著棧幀一起被清理,這個時候還存活在JVM堆中的File對象也是無用的了:

要是人為來判斷非常清晰的就發(fā)現(xiàn)File對象已經(jīng)無用了,那換成JVM它又是如何來判斷對象是否能存活的呢?

引用記數(shù)

引用記數(shù)算法原理比較簡單,想象下有個對象它有一個count屬性,每次引用該對象都會使count加1,假設(shè)JVM在判斷該對象是否存活的時候去檢查這個count屬性,發(fā)現(xiàn)這個屬性不為0說明還有其他對象在引用該對象。

等到checkFile方法執(zhí)行完之后count就會減1變成0:

這樣一來JVM就很容易判斷一個對象是否存活了。

但是引用記數(shù)有一個明顯的缺點,就是無法解決循環(huán)引用的問題比如:A --> B --> A 這樣的對象關(guān)系它是沒有辦法來判斷對象是否該不該回收的。

GC Root(可達性分析)

為什么會被稱為可達性分析算法呢?可以這樣理解如果通過GC Root能到達一個對象那么這個對象就是存活的。那什么樣的對象才是GC Root呢?

在Java語言中,可作為GC Roots的對象包括下面幾種:

  1. 虛擬機棧中引用的對象(棧幀中的本地變量表);
  2. 方法區(qū)中類靜態(tài)屬性引用的對象;
  3. 方法區(qū)中常量引用的對象;
  4. 本地方法棧中JNI(Native方法)引用的對象。

還是用上面的例子,在checkFile方法執(zhí)行時,因為棧幀變量file可做為GC Root所以在執(zhí)行期間JVM是絕對不會回收掉這個File對象:

但是等到checkFile執(zhí)行完成之后,這個棧幀會被彈出,其中的變量也會被釋放,相應(yīng)的沒有GC Root能到達堆中的File對象,這個時候就可以判斷這個對象是一個無用的對象了,然后安全回收。

垃圾收回算法

標記清除

這種算法分兩分:標記、清除兩個階段,

標記階段是從根集合(GC Root)開始掃描,每到達一個對象就會標記該對象為存活狀態(tài),清除階段在掃描完成之后將沒有標記的對象給清除掉。

用一張圖說明:

這個算法有個缺陷就是會產(chǎn)生內(nèi)存碎片,如上圖B被清除掉后會留下一塊內(nèi)存區(qū)域,如果后面需要分配大的對象就會導致沒有連續(xù)的內(nèi)存可供使用。

標記整理

標記整理就沒有內(nèi)存碎片的問題了,也是從根集合(GC Root)開始掃描進行標記然后清除無用的對象,清除完成后它會整理內(nèi)存。

這樣內(nèi)存就是連續(xù)的了,但是產(chǎn)生的另外一個問題是:每次都得移動對象,因此成本很高。

復(fù)制算法

復(fù)制算法會將JVM推分成二等分,如果堆設(shè)置的是1g,那使用復(fù)制算法的時候堆就會有被劃分為兩塊區(qū)域各512m。給對象分配內(nèi)存的時候總是使用其中的一塊來分配,分配滿了以后,GC就會進行標記,然后將存活的對象移動到另外一塊空白的區(qū)域,然后清除掉所有沒有存活的對象,這樣重復(fù)的處理,始終就會有一塊空白的區(qū)域沒有被合理的利用到。

兩塊區(qū)域交替使用,最大問題就是會導致空間的浪費,現(xiàn)在堆內(nèi)存的使用率只有50%。

分代回收

新生代回收

JVM的堆分為新生代和老年代,兩種類型有不同的特性,根據(jù)它們的特性來選擇不同的回收算法,這種算法會將新生代劃分為一塊Eden和二個Survivor區(qū):

如上面的圖有三塊區(qū)域它們會按照8:1:1的比例進行分配,如1000m的堆Eden是800m,二個Survivor各占100m,那它們是如何運行的呢?

  1. 始終會有一塊Survivor是空著的,內(nèi)存使用率是90%
  2. 程序運行會在Eden和其中一塊Survivor 1中分配內(nèi)存
  3. 等到執(zhí)行Minor gc,會將存活下來的對象移動到空著的Survivor 2中
  4. 然后在Eden和Survivor 2中繼續(xù)分配內(nèi)存,Survivor 1空著等著下次使用

這樣就能使內(nèi)存使用率達到90%,也不會產(chǎn)生內(nèi)存碎片。

老年代回收

老年代對象即使進行了垃圾回收,對象的存活率也高,所以采用標記清除或標記整理算法都是不錯的選擇,這里就不做闡述。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • springboot項目數(shù)據(jù)庫配置類DatabaseConfig示例詳解

    springboot項目數(shù)據(jù)庫配置類DatabaseConfig示例詳解

    這篇文章主要介紹了springboot項目數(shù)據(jù)庫配置類DatabaseConfig實現(xiàn)代碼,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • 帶你3分鐘帶你搞定Spring Boot中Schedule

    帶你3分鐘帶你搞定Spring Boot中Schedule

    本文主要圍繞Spring scheduled應(yīng)用實踐進行分享,如果是單體應(yīng)用,使用SpringBoot內(nèi)置的@scheduled注解可以解決大部分業(yè)務(wù)需求,對Spring Boot中Schedule 相關(guān)知識感興趣的朋友一起看看吧
    2024-07-07
  • Spring常用注解及自定義Filter的實現(xiàn)

    Spring常用注解及自定義Filter的實現(xiàn)

    這篇文章主要介紹了Spring常用注解及自定義Filter的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • java定位死鎖的三種方法(jstack、Arthas和Jvisualvm)

    java定位死鎖的三種方法(jstack、Arthas和Jvisualvm)

    這篇文章主要給大家介紹了關(guān)于java定位死鎖的三種方法,分別是通過jstack定位死鎖信息、通過Arthas工具定位死鎖以及通過 Jvisualvm 定位死鎖,文中還介紹了死鎖的預(yù)防方法,需要的朋友可以參考下
    2021-09-09
  • Java容器ArrayList知識點總結(jié)

    Java容器ArrayList知識點總結(jié)

    本篇文章給大家分享了Java容器ArrayList的相關(guān)知識點,對此有需要的朋友可以跟著學習參考下。
    2018-05-05
  • Java單例模式的深入了解

    Java單例模式的深入了解

    這篇文章主要為大家介紹了Java單例模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • java類Circle定義計算圓的面積和周長代碼示例

    java類Circle定義計算圓的面積和周長代碼示例

    要用Java計算圓的周長和面積,需要使用圓的半徑和一些數(shù)學公式,下面這篇文章主要給大家介紹了關(guān)于java類Circle定義計算圓的面積、周長的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • 解決@SpringBootTest 單元測試遇到的坑

    解決@SpringBootTest 單元測試遇到的坑

    這篇文章主要介紹了解決@SpringBootTest 單元測試遇到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 解決程序啟動報錯org.springframework.context.ApplicationContextException: Unable to start web server問題

    解決程序啟動報錯org.springframework.context.ApplicationContextExcept

    文章描述了一個Spring Boot項目在不同環(huán)境下啟動時出現(xiàn)差異的問題,通過分析報錯信息,發(fā)現(xiàn)是由于導入`spring-boot-starter-tomcat`依賴時定義的scope導致的配置問題,調(diào)整依賴導入配置后,解決了啟動錯誤
    2024-11-11
  • 詳解Spring Cloud Eureka多網(wǎng)卡配置總結(jié)

    詳解Spring Cloud Eureka多網(wǎng)卡配置總結(jié)

    本篇文章主要介紹了詳解Spring Cloud Eureka多網(wǎng)卡配置總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04

最新評論

江山市| 松潘县| 牟定县| 塔河县| 政和县| 凤山县| 那曲县| 中宁县| 阜平县| 高雄县| 依兰县| 驻马店市| 喀什市| 镇宁| 巴彦淖尔市| 宽城| 肇州县| 香格里拉县| 喀喇| 肇源县| 吴旗县| 长武县| 台山市| 手机| 萨迦县| 静安区| 大姚县| 德安县| 长春市| 广宗县| 原阳县| 伊金霍洛旗| 睢宁县| 辽宁省| 连州市| 资兴市| 新晃| 永平县| 手游| 焦作市| 黄龙县|