3-JVM垃圾回收演算法和垃圾收集器

来源:https://www.cnblogs.com/Sky0914/archive/2020/05/12/12879125.html
-Advertisement-
Play Games

垃圾回收演算法和垃圾收集器 1.什麼是垃圾回收 對於記憶體當中無用的對象進行回收,如何去判斷一個對象是不是無用的對象。 引用計數法: 每個對象中都會存儲一個引用計數,每增加一個引用就+1,消失一個引用就 1。當引用計數器為0時就會判斷該對象是垃圾,進行回收。 但是這樣會有一個弊端。就是當有兩個對象互相引 ...


垃圾回收演算法和垃圾收集器

1.什麼是垃圾回收

對於記憶體當中無用的對象進行回收,如何去判斷一個對象是不是無用的對象。

引用計數法:

每個對象中都會存儲一個引用計數,每增加一個引用就+1,消失一個引用就-1。當引用計數器為0時就會判斷該對象是垃圾,進行回收。

但是這樣會有一個弊端。就是當有兩個對象互相引用時,那麼這兩個對象的引用計數器都不為0,那麼就不會對其進行回收。

可達性分析:

判斷某個對象是否可到達。有兩種方式判斷是否可到達:

  1. 直接引用(上帝視角GC Roots):就是虛擬機棧幀中的局部或本地變數表、類載入器、static成員、常量引用、Thread等等中的引用直接到達。

    為什麼本地或局部變數表裡面的變數有它出發就可以用來判斷GC Roots的判斷標準呢?

    因為只用它表示這個棧幀正在被壓棧,正在被使用,這個時候再去回收這個對象不是瘋了嘛!!!同理static、常量也是一樣的道理。

  2. 間接引用:通過別人的引用來達到。

併發的可達性分析(併發標記、浮動垃圾):https://mp.weixin.qq.com/s/EgVPlOLArsWb86Kujykn3A

2.垃圾回收的策略

垃圾收集演算法

  • 標記-清除

    先標記

    後清除

    弊端一:會有空間碎片問題,空間不連續;這時如果有大一點的對象進來,發現沒有連續的空間記憶體去進行分配,就會再一次的觸發垃圾回收機制。

    弊端二:在標記和清除的過程中、會掃描整個堆記憶體;會比較耗時。

    有點:簡單、明瞭、好操作。

  • 標記-複製

    一開始將這個記憶體空間一分為二,兩邊大小相等,一邊使用中的,一邊是保留區未使用的。劃分為這樣示例圖:

    在標記和清除之後,將存活的對象複製到另外一邊,在將先前的一邊數據全部清除掉。

    之後以此反覆、兩個迴圈往返。

    類似於堆記憶體中的新生代(Young)區中的Survivor區中的S0、S1,所以堆記憶體中的新生代(Young)區一定用的就是複製演算法。

  • 標記-整理

    先標記

    後整理。

    整理移動之後會得到一片連續的可分配記憶體空間。解決了空間碎片的問題,但是這種方式在標記和整理移動的過程中也是耗時的。


垃圾收集器:評判一個垃圾收集好壞和調優關註的是【高吞吐量、少停頓時間、少垃圾回收次數】

串列:Serial系列;

並行【吞吐量優先】:Paraller系列;

吞吐量:用戶代碼執行的時間 / (用戶代碼執行的時間+垃圾收集時間)99/(99+1)=99%。

適用於後臺運算,不需要太多的交互場景。

併發【停頓時間優先】:CMS、G1;

​ 適用於用戶交互較多的場景,給用戶更好的體驗感;如Web應用。

JVM垃圾收集器調優的原則:儘可能在停頓時間較低的情況下,追求高的吞吐量和少的垃圾回收次數。

官方JVM垃圾收集器建議:

  1. 使用預設垃圾收集器
  2. 調整JVM堆的大小
    • 如果應用程式記憶體空間比較小(比如100MB),直接選擇SerialGC串列收集器。-XX:+UseSerialGC
    • 如果應用程式運行在一個單核的CPU,和沒有停頓時間要求的情況下;可以讓JVM自己去選擇或者選擇SerialGC串列收集器。-XX:+UseSerialGC
    • 如果應用程式更加關註的吞吐量也沒有停頓時間要求的情況下,可以讓JVM自己去選擇或者選擇並行的ParallelGC。-XX+UseParallelGC
    • 如果應用程式對停頓時間要求比較高(比如小於1秒鐘的時間),那麼就選擇CMS或者G1的收集器。-XX:+UseConcMarkSweepGC 或 -XX:+UseG1GC

G1(Garbage-First):JDK7出現,JDK8推薦使用,JDK9預設垃圾收集器。

G1的整個垃圾收集並清理的過程階段大體上和CMS收集器是不變的。在最後一個階段進行刪選回收(選擇性的回收,進行優先順序的回收:優先回收區域(Region)記憶體活對象較少的)。

重新設計記憶體空間如圖所示:

整個記憶體劃分為一個個大小相等的區域(Region)。邏輯上對這些區域(Region)進行標記,這些標記有Eden區,Survivor區和Old區。這時的物理空間上就不在是連續空間了;之前的空間劃分都是連續的空間。假如回收掉某個Old區的數據,這時這個區域也可能會標位Survivor區或者Eden區。

區域(Region)內還有一個記錄rememberd Set。以前會全盤掃描堆記憶體,是比較耗時的。這時會記錄一個對象存活的地方,對象的引用指向;這樣就不用在全盤掃描了耗時比較低。

官方文檔(G1垃圾收集器的前世今生):https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html


Young Generation(新生代)- 垃圾收集演算法一定是標記-複製演算法的實現

Serial:JDK1.3出現的,單線程收集,STW。那時候的CPU還是單核CPU。單線程處理效率比較高,在進行垃圾回收的時候,會暫停業務線程,等待垃圾回收完成之後,在讓業務線程再繼續執行。會搭配老年代的SerialOld配合使用。

這時會出現Stop The World(STW)


ParNew:並行垃圾收集器多個垃圾線程一起跑,STW ,停頓時間較多,更加關註吞吐量

複製演算法、並行多線程垃圾收集器,解決了單線程的局限性,但是還是Stop The World(STW)。


ParallelScavenge

同上


Tenured Generation(老年代)- 這裡是標記-清除、或標記-整理的演算法實現

CMS:JDK5出現的,併發收集,兩個階段會STW(初始標記、重新標記),更加關註停頓時間。在JDK8中已經不推薦使用,JDK8推薦使用G1收集器。

併發:垃圾收集線程和業務代碼線程一起跑。但是並不能做到全程一起執行。

因為垃圾收集線程在執行的時候對垃圾進行標記,這時業務代碼線程也在執行,也會產生新的垃圾。至少在垃圾收集線程在進行標記的階段,業務代碼暫定的是不執行的。

劃分為四個階段:初始標記、併發標記、重新標記、併發清理。

初始標記:第一階段會Stop The World(STW)。這個階段執行的時間是非常快的,如果開啟多個線程,會消耗線程之前的切換反而會增加時間成本。

併發標記:第二階段就是可達性分析,對第一階段的垃圾進行跟蹤。在這個階段垃圾線程和業務線程是一起執行的;為啥可以一起執行呢?因為在第一階段初始標記完成後大局已定,第二階段的併發標記只是做增量的更新。如果此時又產生了垃圾那麼就是浮動垃圾(把原本消亡的對象錯誤的標記為存活狀態),只能等待下次清理。

重新標記:第三階段這時會停止業務代碼的線程Stop The World(STW),會多線程垃圾收集器並行一起跑,一起執行。

併發清理:第四階段垃圾收集線程和業務代碼線程再次一起執行,一起跑。

特點:併發收集,停頓時間較少。

缺點:會產生浮動垃圾。其次由於採用的是標記-清除這樣的演算法會產生大量的空間碎片。


Serial Old:串列的

Paraller Old:並行的


如何查看當前JAVA程式應用使用的是什麼垃圾收集器:

# 查看進程ID
jps -l
8720 org.jetbrains.jps.cmdline.Launcher
10212 org.jetbrains.idea.maven.server.RemoteMavenServer36
3764
15480 sun.tools.jps.Jps
4216 com.hopefun.scm.WebApplication
# 查看當前進程下是否使用UseParallelGC
jinfo -flag UseParallelGC 4216
-XX:+UseParallelGC

趙小胖個人博客


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文主要討論spring boot如何獲取前端傳過來的參數,這些參數主要有兩大類,一類是URL里的參數,一個是請求body里的參數 url里的參數 通過url里傳過來的參數一般有三種方式,下麵我們來看一下 路徑參數 路徑參數就是說在請求路徑里攜帶了幾個參數,比如有一個查詢banner詳情的介面,/v ...
  • 前言 入職新公司到現在也有一個月了,完成了手頭的工作,前幾天終於有時間研究下公司舊項目的代碼。在研究代碼的過程中,發現項目里用到了Spring Aop來實現資料庫的讀寫分離,本著自己愛學習(我自己都不信…)的性格,決定寫個實例工程來實現spring aop讀寫分離的效果。 環境部署 資料庫:MySq ...
  • 1、右鍵點擊項目,選擇properties 2、點擊Project facets 3、在右側的Runtimes中選中apache tomcat 4、勾選Dynamic Web Module 最終改為下麵的樣式,其餘的不要: 即可通過add and remove操作該web項目。 原文地址:https ...
  • 數組實現迴圈隊列 創建3個文件:queueArray.h、queueArray.c、queueArrayTest.c queueArray.h c include include include include "queueArray.h" define ADT QueueArray // 功能: ...
  • 一、 Pagination1. 簡介REST框架支持自定義分頁風格,你可以修改每頁顯示數據集合的最大長度。 分頁鏈接支持以下兩種方式提供給用戶: - 分頁鏈接是作為響應內容提供給用戶 - 分頁鏈接被包含在響應頭中(Content-Range或者Link) 內建風格使用作為響應內容提供給用戶。這種風格 ...
  • 關註公眾號“程式員書單” 加個“星標”,每天帶你讀好書! ​ 學習編程,數據結構是你必須要掌握的基礎知識,那麼數據結構到底是什麼呢? 其實數據結構就是用來描述電腦里存儲數據的一種數學模型,因為電腦里要存儲很多亂七八糟的數據,所以也需要不同的數據結構來描述。 瞭解了基本概念之後,接下來我們再來看看 ...
  • 這篇我們介紹一下ES的聚合功能(aggregation)。聚合是把索引數據可視化處理成可讀有用數據的主要工具。聚合由bucket桶和metrics度量兩部分組成。 所謂bucket就是SQL的GROUPBY,如下: GET /cartxns/_search { "size" : 2, "aggs": ...
  • formula 基於 groovy 實現的公式庫 項目地址 "Github" 語法 比如: 支持公式嵌套: 比如: 快速開始 1. 創建 Formula 對象 formula 1. 運行 formula.run("script") 下麵是例子: 預設公式 這裡只是拋磚引玉,實現瞭如下文本公式: UU ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...