【Java】剛剛!突然!緊急通知!垃圾回收!

【Java】剛剛!突然!緊急通知!垃圾回收!

文章目錄

  • 【Java】剛剛!突然!緊急通知!垃圾回收!
    • 從C語言的內存管理引入:手動回收
    • Java的垃圾回收機制
      • 引用計數器
        • 循環引用問題
      • 可達性分析法與GC Root
        • GC Root的典型例子
      • 標記-清除算法
        • 優點
        • 缺點
      • 復制算法
        • 工作原理
        • 優點
        • 缺點
      • 標記-整理算法
        • 工作原理
        • 優點
        • 缺點
      • 應用場景
      • 分代回收機制
        • 堆內存的分代
        • 各代的垃圾回收策略
          • 新生代垃圾回收(Minor GC)
          • 老年代垃圾回收(Major GC 或 Full GC)
      • 結語

本文將先簡要介紹C語言的手動內存回收機制,然后深入探討Java的垃圾回收(GC)機制,包括引用計數器、可達性分析法、GC root、標記-清除算法、復制算法、標記-整理算法以及分代回收機制。

從C語言的內存管理引入:手動回收

在C語言中,程序員需要手動管理內存的分配和釋放。這主要通過malloccallocreallocfree函數來實現:

  • malloc:用于動態分配內存。
  • calloc:類似于malloc,但它會初始化分配的內存塊為零。
  • realloc:用于調整先前分配的內存塊的大小。
  • free:用于釋放動態分配的內存。

雖然這種手動管理提供了很大的靈活性,但也容易導致內存泄漏(未釋放不再使用的內存)和懸掛指針(指向已釋放內存的指針)。這就需要程序員特別小心,確保每一塊動態分配的內存都能被適時釋放。

例如:

img

我們使用malloc,為結點結構體的指針分配內存。

而在刪除節點時,我們采用free函數來進行內存的釋放。

image-20240530215713904

Java的垃圾回收機制

與C語言不同,Java提供了自動內存管理功能。Java的垃圾回收機制旨在自動回收不再使用的對象所占用的內存,從而減輕程序員的負擔并提高內存管理的安全性。

引用計數器

最簡單的垃圾回收機制之一是引用計數器。它通過維護每個對象的引用計數來跟蹤對象是否可以被回收:

  • 引用計數增加:每當一個新的引用指向對象時,引用計數加1。
  • 引用計數減少:每當一個引用被銷毀或被設置為指向另一個對象時,引用計數減1。
  • 回收對象:當對象的引用計數變為0時,說明該對象不再被使用,可以被回收。

然而,引用計數器存在一個明顯的缺點,即無法處理循環引用(兩個對象相互引用)。

循環引用問題

引用計數器的一大缺點是無法處理循環引用。如下示例:

class Node {Node next;
}Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a;

在這個例子中,即使ab對象的引用離開了作用域,它們的引用計數器仍然不為0(因為它們互相引用),導致內存泄漏。

因此,Java并不使用這種方法作為其主要的垃圾回收策略。

可達性分析法與GC Root

Java采用的是更為先進的可達性分析法。它通過一組被稱為GC Root的根對象作為起點,沿著這些根對象的引用鏈進行搜索。如果一個對象能從GC Root到達,那么它就是可達的(alive),否則就是不可達的,可以被回收。

  • GC Root:通常包括當前在棧中引用的對象、靜態變量引用的對象以及JNI(Java Native Interface)引用的對象等。
  • 可達對象:從GC Root開始,所有可以通過引用鏈訪問到的對象都是可達的。
  • 不可達對象:如果一個對象沒有從GC Root出發的任何引用鏈到達,則認為該對象是不可達的,可以被回收。

image-20240531191720169

GC Root的典型例子
  • 虛擬機棧中的引用對象:如棧幀中的局部變量和輸入參數。
  • 方法區中的靜態引用:如類的靜態屬性。
  • 方法區中的常量引用:如常量池中的引用。

標記-清除算法

image-20240531191636409

標記-清除算法是最早且最基本的垃圾回收算法之一。標記-清除算法分為兩個階段:標記階段和清除階段。

  1. 標記階段
    • 從GC Root集合開始,遍歷對象引用圖,標記所有可達的對象。
    • 標記過程通常是遞歸的,沿著對象引用鏈進行,直到所有可達的對象都被標記。
  2. 清除階段
    • 遍歷堆中的所有對象,回收未被標記的對象。
    • 未標記的對象被認為是不可達的,可以被垃圾回收器回收。

image-20240531191652410

優點
  • 簡單直接:算法簡單,易于實現。
  • 無需移動對象:對象在內存中的位置不會改變,減少了對象移動的開銷。
缺點
  • 內存碎片:清除階段后,未被回收的對象會在堆中留下許多空閑區域,導致內存碎片。頻繁的內存碎片會降低內存分配效率。
  • 標記和清除過程需要遍歷所有對象:在大堆內存中,遍歷所有對象可能導致較長的暫停時間。

復制算法

工作原理

復制算法將堆內存分為兩部分,通常是等大小的兩個半區:From空間和To空間。垃圾回收時,僅使用其中一個半區,另一個半區作為備用空間。

  1. 分配階段

    • 對象只在From空間中分配內存。
    • To空間為空閑的,等待垃圾回收。
  2. 復制和清理階段

    • 從GC Root開始,遍歷所有可達的對象,并將它們復制到To空間。
    • 復制過程中,保持對象的引用關系。
    • 完成復制后,From空間中的所有對象被認為是不可達的,可以被回收。
    • 交換From和To空間的角色,下一次分配和垃圾回收使用新的From空間。
  3. 示例

    假設有A塊等待垃圾回收:

    image-20240531191812980

    回收之后會變成~:

    image-20240531191937607

優點
  • 無內存碎片:對象被緊湊地復制到新的空間,不會留下內存碎片。
  • 分配速度快:由于始終從一個連續的空閑區域分配內存,分配速度很快。
缺點
  • 內存利用率低:由于堆內存被劃分為兩個半區,同時只使用一半內存,導致內存利用率低。
  • 對象復制開銷:復制對象到新的空間需要額外的開銷,特別是當對象較多時。

標記-整理算法

標記-整理算法(Mark-Compact Algorithm)是一種改進的垃圾回收算法,用于解決標記-清除算法產生的內存碎片問題。它結合了標記-清除和復制算法的優點,通過整理內存來提高內存分配效率。下面將詳細分析標記-整理算法的工作原理、優缺點及其適用場景。

工作原理

標記-整理算法也分為兩個主要階段:標記階段和整理階段。

  1. 標記階段

    • 從GC Root集合開始,遍歷對象引用圖,標記所有可達的對象。
    • 這一步與標記-清除算法中的標記階段相同,標記過程是遞歸的,沿著對象引用鏈進行,直到所有可達的對象都被標記。

    image-20240531192004795

  2. 整理階段

    • 遍歷整個堆,將所有存活的對象向一端移動(通常是堆的起始位置),保持對象之間的緊密排列。
    • 更新所有對象的引用,以反映它們的新位置。
    • 移動完成后,釋放未被標記對象的內存,未被標記的對象被回收,形成一塊連續的空閑區域。

    image-20240531192017499

優點
  • 無內存碎片:對象被緊密排列在一起,沒有內存碎片,提高了內存利用率。
  • 高效的內存分配:由于所有存活對象被移動到堆的一端,剩下的內存是連續的,內存分配速度更快。
  • 適用于長生命周期對象:尤其適合老年代(Old Generation)的垃圾回收,因為老年代對象生命周期較長,不需要頻繁移動。
缺點
  • 對象移動開銷:整理階段需要移動對象,并更新引用,增加了額外的開銷,尤其是在老年代中存活對象較多時。
  • 暫停時間長:標記和整理過程會導致應用暫停,可能影響實時性要求較高的應用。

標記-整理算法減少了內存碎片化,同時避免了復制算法中需要雙倍內存的缺點。

應用場景

  • 標記-清除算法:適用于內存緊張、不希望頻繁移動對象的場景,如老年代(Old Generation)的垃圾回收。
  • 復制算法:適用于對象生命周期短、需要快速回收的場景,如新生代(Young Generation)的垃圾回收。JVM中的新生代垃圾回收器通常使用復制算法。
  • 標記-整理算法:對象較大且數量較多的場景,當對象較大且數量較多時,標記-整理算法可以通過緊湊排列對象,減少內存浪費,提高內存利用率。

分代回收機制

分代回收機制的核心思想是將堆內存劃分為幾個代,根據對象的生命周期長短來進行不同的管理和回收。大多數對象的生命周期很短,少數對象存活時間較長。通過這種劃分,可以有針對性地采用不同的垃圾回收算法,提高回收效率和性能。

堆內存的分代

JVM中的堆內存通常劃分為以下幾代:

新生代(Young Generation)

  • Eden區:所有新創建的對象首先分配在Eden區。
  • 兩個Survivor區(S0和S1):用于在新生代中進行對象復制和存活對象的管理。每次垃圾回收時,存活的對象從Eden區和一個Survivor區復制到另一個Survivor區。

老年代(Old Generation):存活時間較長、從新生代晉升的對象存放在老年代。

永久代(PermGen)或元空間(Metaspace):存儲類的元數據(方法、類結構等)。在Java 8之前為永久代(PermGen),Java 8及之后為元空間(Metaspace)。

各代的垃圾回收策略
新生代垃圾回收(Minor GC)

新生代的垃圾回收頻繁,通常采用復制算法(Copying Algorithm)。當Eden區填滿時,觸發Minor GC:

  1. 存活對象復制:存活的對象從Eden區和一個Survivor區復制到另一個Survivor區。
  2. 對象晉升:當對象經過多次Minor GC后依然存活(達到一定年齡),或Survivor區空間不足時,存活對象晉升到老年代。
  3. Eden區清空:所有存活對象復制后,Eden區和一個Survivor區被清空,另一個Survivor區保留存活對象。

Minor GC的頻率較高,但由于新生代對象生命周期短,存活對象少,因此回收速度較快。

老年代垃圾回收(Major GC 或 Full GC)

老年代的垃圾回收通常采用標記-整理算法(Mark-Compact Algorithm) 或 標記-清除算法(Mark-Sweep Algorithm)

  1. 標記階段:從GC Root開始,標記所有可達的對象。
  2. 整理階段(標記-整理算法):將所有存活對象向一端移動,保持對象之間的緊密排列,釋放未標記對象的內存。
  3. 清除階段(標記-清除算法):回收未標記對象的內存,但可能產生內存碎片。

Major GC或Full GC的頻率較低,但由于老年代對象較多且存活時間長,回收過程較慢,可能導致較長的暫停時間。

結語

Java的垃圾回收機制通過自動化內存管理,極大地減輕了開發者的負擔,同時提升了程序的安全性和穩定性。盡管Java的GC機制復雜多樣,但其核心思想都是為了更高效地管理內存,避免內存泄漏和碎片化。

許多現代編程語言,如Java、C#、Python等,都內置了垃圾回收機制。通過學習垃圾回收,可以更深入地理解這些語言的設計思想和實現細節。不同語言的垃圾回收機制有所不同,了解這些差異可以幫助我們在具體語言中應用最佳實踐,編寫高效的代碼。

此后,筆者還會介紹Java中的垃圾回收器相關知識,以及有可能的JVM調優。

參考資料與文獻:

20、垃圾回收算法之可達性分析法和GC Roots是什么?_嗶哩嗶哩_bilibili

【JVM】萬字長文!深入詳解Java垃圾回收(GC)機制_java gc-CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19761.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19761.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19761.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot六種API請求參數讀取方式

SpringBoot六種API請求參數讀取方式 同步請求和異步請求 同步: 指單線程依次做幾件事異步: 指多線程同時做幾件事 同步請求: 指客戶端瀏覽器只有一個主線程, 此線程負責頁面的渲染和發出請求等操作, 如果此主線程發出請求的話則停止渲染而且會清空頁面顯示的內容 直到服務器響…

優化基礎(二):線性組合、仿射組合、錐組合、凸組合、線性集合、仿射集合、錐集合、凸集合的理解

文章目錄 前言組合線性組合 (linear combination)仿射組合 (affine combination)錐組合 (conic combination)凸組合 (convex combination) 集合仿射集合凸集合 練習:哪個圖形是凸的,哪個是仿射的?參考資料 前言 組合側重于描述由一些基點生成…

越洗越黑”的Pandas數據清洗

引言 先來一個腦筋急轉彎活躍一下枯燥工作日常,問:“什么東西越洗越黑?” 有沒有猜到的?猜不到我告訴你吧! 答案是“煤球”。那么這個腦機急轉彎跟我們要討論的話題有沒有關系呢? 嗯是的,還是沾…

三相智能電表通過Modbus轉Profinet網關與PLC通訊案例

Modbus轉Profinet網關(XD-MDPN100/300)的主要功能是實現Modbus協議和Profinet協議之間的轉換和通信。Modbus轉Profinet網關集成了Modbus和Profinet兩種協議,支持Modbus RTU主站/從站,并可以與RS485接口的設備,它自帶網…

「前端+鴻蒙」核心技術HTML5+CSS3

1、CS架構與BS架構 CS架構(Client-Server):客戶端/服務器架構。用戶通過客戶端軟件與服務器進行交互,客戶端需要安裝特定的軟件才能訪問服務器上的資源。BS架構(Browser-Server):瀏覽器/服務器架構。用戶通過瀏覽器訪問服務器上的網頁,無需安裝額外的軟件,所有的交互都…

接口請求參數為文件時如何測試

方法 工具:Postman 步驟:①點擊body②點擊form-data③選擇key類型為fie ④輸入參數名⑤選擇參數上傳⑥發送請求

對稱二叉樹(oj題)

一、題目鏈接https://leetcode-cn.com/problems/symmetric-tree/ 二、題目思路 給你一個二叉樹的根節點 root , 檢查它是否軸對稱的思路: 1.將該樹的左子樹和右子樹,當做兩棵樹,調用 判斷兩棵樹是否對稱相等的函數 2.判斷兩顆樹是否對稱相…

告別低效提問:掌握BARD技巧,讓AI成為你的智能助手!

今天只聊一個主題:提示詞 Prompt。 說到提示詞,大家可能都看過GPT的高級示例,那些幾百字的提示詞,寫起來確實不容易。 那么,如何寫出同樣效果的提示詞呢? 有沒有什么公式或者系統學習的方法?…

在Linux/Ubuntu/Debian中使用lshw查看系統信息

在Linux/Ubuntu/Debian中使用lshw查看系統信息 lshw 是一個用于顯示硬件配置的命令,可以提供系統硬件的詳細信息,包括 CPU、內存、硬盤、主板等。該命令需要超級用戶權限來獲取詳細信息。 常見用法: 顯示所有硬件信息: sudo l…

木葉飛舞之【機器人ROS2】篇章_第三節、給turtlebot3安裝realsense深度相機

我們做視覺slam時會用到深度相機,但是gazebo的turtlebot3中只有rgb相機,沒有深度,因此本節會修改代碼,來給我們的小烏龜增加一個rgbd相機。 效果展示 發布topic如下圖 圖片大小都是640*480 1. 修改model.sdf文件 1.1 路徑位置…

射頻功率限幅器簡略

在功率輸入保護方面,限幅器是最好用的器件之一,可以保護后級電路不受超限功率的損害,限幅器其實像TVS功能一樣,讓超過閾值的功率釋放到接地上,來達到限制幅度的目的,目前限幅器的限幅幅度大多都大于15dBm,很…

啟智CV機器人,ROS, ubuntu 18.04

資料: https://wiki.ros.org/kinetic/Installation/Ubuntu https://blog.csdn.net/qq_44339029/article/details/120579608 http://wiki.ros.org/melodic/Installation/Ubuntu https://github.com/6-robot/wpb_cv 一、安裝ros環境 裝VM。 裝ubuntu18.04 desktop.…

100道面試必會算法-27-美團2024面試第一題-前綴和矩陣

100道面試必會算法-27-美團2024面試第一題-前綴和矩陣 問題解讀 給定一個 n x n 的二進制矩陣,每個元素是 0 或 1。我們的任務是計算矩陣中所有邊長為 k 的子矩陣中,包含特定數量 1 的情況。例如,我們希望找到所有邊長為 k 的子矩陣中包含 k…

Java實現成績管理系統

1.思路分析實現 要求一和要求二,一個要求使用順序表一個使用鏈表,但又因為這兩個都是List的實現類,所以我就使用多態的形式通過一個方法進行實現上面兩種內容,需要用什么方法實現就傳入什么實現類,形參是List類型。創建…

【學習Day3】計算機基礎

?🏻記錄學習過程中的輸出,堅持每天學習一點點~ ??希望能給大家提供幫助~歡迎點贊👍🏻收藏?評論?🏻指點🙏 1.5.4 Cache替換算法 Cache的頁面淘汰算法 常用替換算法有: ? 隨機替換算法RA…

vue3 setup 使用 beforeRouteEnter 組件內路由守衛

vue3 setup 使用 beforeRouteEnter 組件內路由守衛 setup 中只有onBeforeRouteLeave、onBeforeRouteUpdate兩個鉤子函數&#xff0c; 沒有beforeRouteEnter對應的鉤子函數&#xff0c;所以無法在setup中直接使用 <script setup> onBeforeRouteLeave((to, from) > {// …

Android基礎-性能優化

在Android平臺上進行性能優化是確保應用程序高效、穩定且流暢運行的關鍵過程。以下將詳細闡述Android性能優化的各個方面&#xff0c;包括但不限于布局優化、繪制優化、內存管理、網絡優化、安裝包優化以及針對不同版本的Android系統進行適配等。 一、布局優化 布局優化的核心…

3D軟件開發的相關技術

3D開發涉及到廣泛的技術和工具&#xff0c;涵蓋了多個領域&#xff0c;包括計算機圖形學、編程、設計、物理模擬等。以下是3D開發中常用的技術和工具&#xff0c;掌握這些技術需要廣泛的知識和實踐&#xff0c;項目的成功依賴于對這些技術的有效整合和應用。北京木奇移動技術有…

音視頻開發14 FFmpeg 視頻 相關格式分析 -- H264 NALU格式分析

H264簡介-也叫做 AVC H.264&#xff0c;在MPEG的標準?是MPEG-4的?個組成部分–MPEG-4 Part 10&#xff0c;?叫Advanced Video Codec&#xff0c;因此常常稱為MPEG-4 AVC或直接叫AVC。 原始數據YUV,RGB為什么要壓縮-知道就行 在?視頻傳輸過程中&#xff0c;視頻?件的傳輸…

熱敏電阻的設計

熱敏電阻(NTC)的作用&#xff1a;抑制開機時的浪涌電流。防止開機瞬間產生的浪涌電流損壞后面的元件。 取值依據:根據對開機的脈沖電流&#xff08;浪涌電流&#xff09;小于多少A&#xff1f; 由,這個U是指最大輸入電壓&#xff0c;I為要求的浪涌電流。 NTC是負溫度系數的熱…