JVM-垃圾回收器與內存分配策略詳解

1.如何判斷對象已死

1.1 對象引用的4種類型(強軟弱虛)

1.1.1 強引用

特點:最常見的引用類型,只要強引用存在,對象絕不會被回收

Object strongObj = new Object();  // 強引用

注意:集合類型,如果對象不再使用,應當及時清除,避免內存泄漏

1.1.2 軟引用

特點:內存不足時才會被回收,適合實現緩存

SoftReference<byte[]> softRef = new SoftReference<>(new byte[1024*1024*10]); // 10MB

?適用場景:

  1. 緩存(EhCache中使用軟引用,一旦觸發內存不足時,就會由JVM自動清理數據,釋放內存)

緩存本身的含義:可刪除

1.1.3 弱引用

特點:下次GC時必定被回收,適合維護非必要數據

 // 弱引用基本示例
WeakReference<String> weakRef = new WeakReference<>(new String("Weak Object"));     

?適用場景:

? ? ? ? 臨時的數據

1.1.4 虛引用

1.1.5 其他

1.1.5.1 ReferenceQueue

referenceQueue(引用隊列)是Java引用類型體系中的關鍵組件,與SoftReference、WeakReference和PhantomReference配合使用,提供了對象生命周期監控的機制。

  1. ?通知機制:當被引用的對象達到相應回收狀態時,引用對象本身會進入隊列
  2. ??非阻塞設計:提供poll()和remove()兩種獲取方式
  3. ?GC協作:由垃圾收集器在適當時候自動入隊

?工作流程

?創建引用對象 → 關聯ReferenceQueue → 對象被回收 → 引用對象入隊 → 客戶端處理
引用類型入隊時機典型用途
虛引用對象被回收且finalize完成后精準資源清理
弱引用對象被GC回收時緩存/臨時映射
軟引用內存不足被回收時內存敏感緩存
強引用從不入隊常規對象引用

?

1.1.6 使用案例

軟引用緩存,清除無效的key


/*** 弱引用緩存*/public class WeakCache<K, V> {private final ConcurrentHashMap<K, WeakReference<V>> cache = new ConcurrentHashMap<>();private final ReferenceQueue<V> queue = new ReferenceQueue<>();public void put(K key, V value) {cleanUp();cache.put(key, new WeakReference<>(value, queue));}// 清除緩存中已釋放的引用(原因:value是弱引用、但是key是強引用,value被釋放了,key沒有作用,應當也被釋放)private void cleanUp() {Reference<? extends V> ref;while ((ref = queue.poll()) != null) {Reference<? extends V> finalRef = ref;cache.values().removeIf(weakRef -> weakRef == finalRef);}}
}

1.2 判斷對象已死

1.2.1 方案1:引用計數算法

核心思想
  • 每個對象維護一個引用計數器,記錄有多少引用指向它
計數規則
  • 新引用指向對象時,計數器+1
  • 引用失效時,計數器-1
  • 計數器=0時立即回收對象

1.2.2 方案2:可達性分析算法

核心思想
  • 通過GC Roots作為起點,遍歷對象引用鏈
判定規則
  • 從GC Roots不可達的對象判定為垃圾
  • 通常在特定時間點(如堆空間不足時)執行
GC Roots有哪些

GC Roots是垃圾回收的起點,所有從這些根對象直接或間接可達的對象都被視為存活對象。以下是Java中常見的GC Roots類型:

  • 虛擬機棧(棧幀中的本地變量表)中的引用對象
public void method() {Object localObj = new Object();  // localObj是GC Root// 方法執行期間,localObj引用的對象不會被回收   
}當前所有正在執行的方法中的局部變量和參數包括Java方法、native方法的棧幀中的引用
  • ???方法區中類靜態屬性引用的對象
class MyClass {static Object staticObj = new Object();  // staticObj是GC Root
}特點:類的靜態變量引用的對象直到ClassLoader卸載前都會保持強引用
  • 方法區中常量引用的對象
class MyClass {static final String CONSTANT = "常量";  // CONSTANT是GC Root
}特點:包括字符串常量池中的引用編譯期常量(constantValue屬性)不算真正的GC Root

  • 本地方法棧中JNI(Java Native Interface)引用的對象
public native void nativeMethod(Object obj);  // native代碼中的obj引用Java調用native方法時傳入的參數對象
全局JNI引用(NewGlobalRef創建)也是GC Root
  • 被同步鎖(synchronized)持有的對象
  • Java虛擬機內部的引用

包括:

  • 基本類型對應的Class對象

  • 常駐異常對象(NullPointerException等)

  • 系統類加載器

  • 類加載器管理的Class對象

1.2.3 工作原理對比

特征引用計數可達性分析
觸發時機實時(引用變更時)周期性/按需
執行速度分散的微小停頓集中式停頓(STW問題)
內存回收立即回收延遲回收
實現復雜度簡單復雜
對象判定計數器=0GC Roots不可達

?

1.2.4 優缺點分析

1.2.4.1 引用計數的優缺點

優點

  1. 立即回收內存,減少內存占用
  2. 垃圾回收開銷平均分配到程序運行中
  3. 不需要STW(Stop-The-World)暫停

缺點:

  • 計數器維護帶來額外內存開銷
  • 頻繁更新計數器影響性能
  • 循環引用問題(主要缺陷)
// 引用計數無法處理的場景   
class A { B b; }   
class B { A a; }void createCycle() {A a = new A();  // A計數=1B b = new B();  // B計數=1a.b = b;        // B計數=2b.a = a;        // A計數=2// 即使外部引用消失...a = null;       // A計數=1b = null;       // B計數=1// 對象仍無法回收!   
}// 可達性分析可以正確處理
1.2.4.2 可達性分析的優缺點

優點

  1. 能正確處理循環引用
  2. 回收效率高(集中處理)
  3. 現代JVM采用的成熟方案

缺點

  1. 需要STW暫停應用線程
  2. 實現復雜度高(需要準確識別GC Roots)
  3. 內存回收不及時

java采用可達性分析算法

2.垃圾收集算法

分代收集理論

標記-清除算法

標記-復制算法

標記-整理算法

算法細節(根節點枚舉、安全點、安全區域、記憶集與卡表、寫屏障、并發的可達性分析)

3.常見的垃圾收集器

3.1 serial

3.2 parNew

3.3 Parallel Scavenge

3.4 serial old

3.5 Parallel Old

3.6 CMS

3.7 G1

3.8 ZGC

4. 內存分配策略

對象優先分配到Eden區

大對象直接進入老年代

長期存活的對象將進入老年代

動態對象年齡判斷

空間分配擔保

垃圾回收的優化案例

fullGc問題

對于絕對不可接受Full GC的系統:

  1. 商用解決方案:Azul Zing(C4 GC)、IBM Balanced GC
  2. 內存架構改造
    • 堆外內存存儲(HBase/OFF-Heap)
    • 分布式緩存集群
  3. 服務拆分:將內存敏感組件獨立部署

最佳實踐:某證券交易所系統通過G1+堆外緩存方案,實現連續18個月零Full GC,老年代內存通過并發標記和定期混合回收保持85%以上可用率。

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

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

相關文章

新手向:簡易Flask/Django個人博客

從零開始搭建個人博客:Flask與Django雙版本指南 本文將詳細講解如何使用兩種主流Python框架構建功能完整的個人博客系統。我們將從零開始,分別使用輕量級的Flask框架和功能全面的Django框架實現以下核心功能: 用戶認證系統: 用戶注冊/登錄/注銷功能 密碼加密存儲 會話管理…

使用 Trea cn 設計 爬蟲程序 so esay

使用 Trea cn 設計 爬蟲程序 so esay 在現代數據驅動的時代&#xff0c;網絡爬蟲已成為數據采集的重要工具。傳統的爬蟲開發往往需要處理復雜的HTTP請求、HTML解析、URL處理等技術細節。而借助 Trea CN 這樣的AI輔助開發工具&#xff0c;我們可以更高效地構建功能完善的爬蟲程…

MySQL Redo Log

MySQL Redo Log MySQL主從復制&#xff1a;https://blog.csdn.net/a18792721831/article/details/146117935 MySQL Binlog&#xff1a;https://blog.csdn.net/a18792721831/article/details/146606305 MySQL General Log&#xff1a;https://blog.csdn.net/a18792721831/artic…

項目實戰1:Rsync + Sersync 實現文件實時同步

項目實戰&#xff1a;Rsync Sersync 實現文件實時同步 客戶端中數據發生變化&#xff0c;同步到server端&#xff08;備份服務器&#xff09;。 Rsync&#xff1a;負責數據同步&#xff0c;部署在server端。 Sersync&#xff1a;負責監控數據目錄變化&#xff0c;并調用rsync進…

Spring Boot 全 YAML 配置 Liquibase 教程

一、項目初始化配置 1.1 創建 Spring Boot 項目 通過 Spring Initializr 生成基礎項目&#xff0c;配置如下&#xff1a; ??Project??: Maven??Language??: Java??Spring Boot??: 3.5.3&#xff08;最新穩定版&#xff09;??Project Metadata??: Group: com…

STM32-驅動OLED顯示屏使用SPI(軟件模擬時序)實現

本章概述思維導圖&#xff1a;SPI通信協議SPI通信協議介紹SPI通訊&#xff1a;高速的、串行通訊、全雙工、同步、總線協議&#xff1b;&#xff08;通過片選信號選中設備&#xff09;&#xff1b;注&#xff1a;SPI通訊通過片選信號選中設備&#xff0c;串口通訊通過端口號選中…

Easy系列PLC相對運動指令實現定長輸送(ST源代碼)

匯川Easy系列PLC總線伺服轉矩控制功能塊 Easy系列PLC總線伺服轉矩控制功能塊(詳細PDO配置+完整ST源代碼)_pdo中添加目標力矩然后映射到軸中-CSDN博客文章瀏覽閱讀215次。Easy系列PLC如何實現輪廓速度模式PV速度模式Easy系列PLC如何實現輪廓速度模式PV速度控制_匯川easy plc輪廓…

SpringCloud學習第一季-4

目錄 16.SpringCloud Alibaba Nacos服務注冊和配置中心 SpringCloud Alibaba簡介 1. 為什么出現 SpringCloud Alibaba 2. SpringCloud Alibaba帶來了什么 2.1 能干什么 2.2 去哪里下載 2.3 怎么玩 3. 學習資料的獲取 17.SpringCloud Alibaba Nacos服務注冊和配置中心 …

嵌入式開發學習———Linux環境下數據結構學習(五)

折半查找&#xff08;二分查找&#xff09;適用于已排序的數組&#xff0c;通過不斷縮小查找范圍定位目標值。int binarySearch(int arr[], int size, int target) {int left 0, right size - 1;while (left < right) {int mid left (right - left) / 2;if (arr[mid] t…

(一)React +Ts(vite創建項目/useState/Props/Interface)

文章目錄 項目地址 一、React基礎 1.1 vite創建 1. 創建項目 2. 安裝項目所需環境 1.2 jsx 1. 三元表達式 1.3 基礎 1. 創建第一個組件 2. 安裝boostrap 3. 插件常用命令 4. map 二、組件 2.1 useState 1. useState 2. 使用 3.更新對象 4. 更新數組(增,刪,改) 5. 使用immer…

網關和BFF是如何演化的

BFF&#xff08;Backend For Frontend&#xff09;:對返回的數據結構進行聚合、裁剪、透傳等適配邏輯。 適用于API網關之后的數據聚合、裁剪與透傳簡化客戶端邏輯&#xff0c;減少網絡開銷敏感數據過濾 BFF邏輯層 架構沒有最好&#xff0c;要看是否滿足當前的業務場景。 業務的…

SQL中的WITH語句(公共表表達式CTE)解釋

SQL中的WITH語句&#xff08;公共表表達式CTE&#xff09; WITH語句&#xff0c;也稱為公共表表達式&#xff08;Common Table Expression&#xff0c;CTE&#xff09;&#xff0c;是SQL中一種強大的功能&#xff0c;它允許你創建臨時結果集&#xff0c;這些結果集可以在后續的…

服務器地域選擇指南:深度分析北京/上海/廣州節點對網站速度的影響

更多云服務器知識&#xff0c;盡在hostol.com你準備開一個覆蓋全國的線上零食店&#xff0c;現在萬事俱備&#xff0c;只差一個核心問題沒解決&#xff1a;你唯一的那個總倉庫&#xff0c;應該建在哪里&#xff1f;是建在哈爾濱&#xff0c;讓南方的朋友下單后&#xff0c;一包…

桶排序-Java實現

桶排序是一種分配式排序算法&#xff0c;將元素分到有限數量的桶里&#xff0c;每個桶再單獨排序&#xff08;比如用插入排序&#xff09;&#xff0c;最后依次把各個桶中的元素取出來即完成排序。 時間復雜度&#xff1a;最佳 O(n) | 平均 O(n n/k k) | 最差 O(n) 空間復雜…

oracle知識

這里寫自定義目錄標題Oracle常用的數據類型&#xff1a;Oracle實操&#xff1a;創建數據表Oracle約束建表的時候設置約束&#xff1a;表創建后添加添加約束&#xff1a;Oracle常用的數據類型&#xff1a; Oracle實操&#xff1a;創建數據表 Oracle約束 建表的時候設置約束&…

超級人工智能+無人機操控系統,振興鄉村經濟的加速器,(申請專利應用),嚴禁抄襲!

無人機邊緣智能系統&#xff1a;山林珍稀資源探測的完整架構與實戰指南本人設計的多模態邊緣AI系統已在秦嶺山區完成實地驗證&#xff0c;對7種高價值食用菌識別準確率達94.3%&#xff0c;定位誤差小于0.8米一、前沿技術融合的商業化機遇根據Gartner 2025年技術成熟度曲線分析&…

用騰訊地圖寫一個逆地址解析(很詳細)

首先說明以下代碼適合有前端基礎知識的同學。以下是css和html部分<!DOCTYPE html><html lang"zh-CN"><!-- lang是用來申明語言類型&#xff0c;這里申明為中文&#xff08;zh&#xff09;中國大陸&#xff08;CN&#xff09;補充中文繁體為zh-TW --&g…

在 Vue3+Vite+TypeScript 項目中使用 svg 文件并支持自定義樣式

參考文檔&#xff1a;vite-svg-loader 安裝與配置 安裝插件 pnpm add vite-svg-loader -D配置 // vite.config.ts import svgLoader from vite-svg-loaderexport default defineConfig({plugins: [vue(),svgLoader({defaultImport: component})] })使用 <script setup …

ShimetaPi M4-R1:國產高性能嵌入式平臺的異構計算架構與OpenHarmony生態實踐

在全球化芯片供應鏈波動及樹莓派等硬件持續漲價的背景下&#xff0c;ShimetaPi M4-R1 作為全棧國產化嵌入式開發平臺&#xff0c;以 高性能異構計算架構 和 開源鴻蒙原生支持 為核心突破點&#xff0c;填補了中高端邊緣設備開發的國產方案空白。其基于瑞芯微 RK3568B2 的硬件設…

zookeeper分布式鎖 -- 讀鎖和寫鎖實現方式

讀鎖和寫鎖讀鎖: 是共享鎖,讀鎖與讀鎖是可以兼容的,所以同時有多個請求都可以持有寫鎖: 是獨占鎖,寫鎖與任何鎖都互斥,所以只有一個請求持有,這個請求釋放寫鎖其他請求才能持有一旦持有寫鎖,說明數據在發送變化就不能讀了,自然一個請求就不能出現讀鎖和寫鎖共存的情況總結: 讀鎖…