【譯】Java垃圾回收演算法[截止到Java 9]

来源:https://www.cnblogs.com/sxpujs/archive/2020/04/05/12638925.html
-Advertisement-
Play Games

原文: "Java Garbage Collection Algorithms [till Java 9]" 垃圾回收(Garbage collection,GC)一直是 Java 流行背後的重要特性之一。垃圾回收是 Java 中用於釋放未使用記憶體的機制。本質上,它跟蹤所有仍在使用的對象,並將其餘的 ...


原文:Java Garbage Collection Algorithms [till Java 9]

垃圾回收(Garbage collection,GC)一直是 Java 流行背後的重要特性之一。垃圾回收是 Java 中用於釋放未使用記憶體的機制。本質上,它跟蹤所有仍在使用的對象,並將其餘的標記為垃圾。Java 的垃圾收集被認為是一種自動記憶體管理模式,因為程式員不必將對象指定為準備釋放的對象。垃圾回收在低優先順序線程上運行。

目錄:

對象生命周期(Object Life Cycle)

Java 的對象生命周期可以分為3個階段:

  1. 對象創建(Object creation),如使用關鍵字new。
  2. 使用中的對象(Object in use)
  3. 對象銷毀(Object destruction)

垃圾回收演算法(Garbage collection algorithms)

標記清除(Mark and sweep)

它是初始的和非常基本的演算法,分兩個階段運行:

  1. 標記存活對象(Marking live objects)– 找出所有仍然活著的對象
  2. 刪除不可到達的對象(Removing unreachable objects)

首先,GC 將一些特定的對象定義為垃圾收集根(Garbage Collection Roots)。 例如,當前執行方法的局部變數和輸入參數、活動線程、載入類的靜態欄位和 JNI 引用。現在,GC 遍歷記憶體中的整個對象圖,從這些根開始,然後從根引用到其他對象。 GC訪問的每個對象都被標記為活動的。

第二階段是清除未使用的對象以釋放記憶體。這可以通過多種方式來實現,例如:

  • 常規刪除(Normal deletion)- 常規刪除會刪除未引用的對象以釋放空間,並留下引用的對象和指針。 記憶體分配器(類似於散列表)保存對可以分配新對象的空閑空間塊的引用。 它通常被稱為標記-清除(mark-sweep)演算法。

  • 刪除-壓縮(Deletion with compacting)- 只刪除未使用的對象是沒有效率的,因為空閑記憶體塊分散在存儲區域中,如果創建的對象足夠大並且沒有找到足夠大的記憶體塊,就會導致 OutOfMemoryError 錯誤。 為瞭解決這個問題,在刪除未引用的對象之後,將對剩餘的引用對象進行壓縮。 這裡的壓縮指的是將被引用的對象移動到一起的過程。 這使得新的記憶體分配更加容易和快速。它通常被稱為標記-清除-壓縮(mark-sweep-compact)演算法。

  • 複製刪除(Deletion with copying)- 與標記和壓縮的方法非常類似,因為他們也重新安置所有存活對象。 重要的區別在於遷移的目標是不同的記憶體區域。它通常被稱為標記-複製(mark-copy)演算法。

併發標記清除垃圾回收(Concurrent mark sweep (CMS) garbage collection)

它試圖通過與應用程式線程併發執行大部分垃圾收集工作來最小化垃圾收集引起的暫停。 該演算法在年輕代中採用並行stop-the-world標記複製(mark-copy)演算法,在老年代中採用大多併發的標記清除(mark-sweep)演算法。

由於從JDK9開始CMS被標記為廢棄,並且在JDK14中完全移除,因此不再介紹該收集器。

串列收集器(Serial garbage collection)

該演算法對年輕代使用標記-複製(mark-copy),對老年代使用標記-清除-壓縮(mark-sweep-compact)。它在單線程上工作。在執行時,它會凍結所有其他線程,直到垃圾回收操作結束。

由於串列垃圾收集具有線程凍結(thread-freezing)的特性,因此只適用於非常小的程式。

要使用 Serial GC,請使用以下 JVM 參數:

-XX:+UseSerialGC

並行收集器(Parallel garbage collection)

類似於串列GC,年輕代使用標記-複製(mark-copy),老年代使用標記-清除-壓縮(mark-sweep-compact)。多個併發線程用於標記和複製/壓縮階段。可以使用 -XX:ParallelGCThreads=N 選項配置線程數。

並行垃圾收集器適用於主要目標是通過有效利用現有系統資源來提高吞吐量的多核機器上。使用這種方法,可以大大減少GC的周期時間。

直到Java 8,並行收集器是預設的垃圾收集器。從 Java 9開始,G1是32位和64位伺服器配置的預設垃圾收集器。

要使用並行 GC,請使用以下 JVM 參數:

-XX:+UseParallelGC

G1(垃圾優先)收集器(G1 garbage collection)

G1(Garbage First)垃圾收集器在Java 7中可用,被設計為CMS收集器的長期替代品。 G1收集器是一個並行、併發和增量壓縮的低暫停垃圾收集器。

這種方法包括將記憶體堆分割成多個小區域(通常是2048)。每個地區被標記為年輕代(進一步分為伊甸園區域或幸存者區域)或老年代。這使得GC可以避免立即回收整個堆,而是以增量方式處理問題。這意味著一次只考慮區域的一個子集。

G1持續跟蹤每個區域包含的存活數據量。此信息用於確定包含最多垃圾的區域; 因此它們首先被回收。這就是為什麼它被命名為垃圾優先收集。

與其他演算法一樣,不幸的是,壓縮操作使用 Stop the World 方法進行。但是根據它的設計目標,你可以為它設定具體的性能目標。您可以配置暫停時間,例如,在任何給定的時間內,暫停時間不超過10毫秒。G1收集器將盡最大努力以高概率實現這一目標(但不是確定性的,由於操作系統級別的線程管理,這將是實時性的困難)。

如果你想在 Java 7 或 Java 8 機器上使用,請使用如下的 JVM 參數:

-XX:+UseG1GC

G1自定義選項

標記 描述
-XX:G1HeapRegionSize=16m 堆區域的大小。該值的大小為2的冪,範圍從1MB到32MB。我們的目標是根據最小的Java 堆大小設置大約2048個區域
-XX:MaxGCPauseMillis=200 為期望的最大暫停時間設置目標值。預設值是200毫秒。指定的值不適合堆大小
-XX:G1ReservePercent=5 這決定了堆中的最小儲備
-XX:G1ConfidencePercent=75 這是信心繫數暫停預測啟髮式
-XX:GCPauseIntervalMillis=200 這是每個MMU的暫停間隔時間片(以毫秒為單位)

GC自定義選項

GC配置標記

標記 描述
-Xms2048m -Xmx3g 設置初始和最大堆大小(年輕代+老年代)
-XX:+DisableExplicitGC 這將導致JVM忽略應用程式對System.gc()方法的任何調用。
-XX:+UseGCOverheadLimit This is the use policy used to limit the time spent in garbage collection before an OutOfMemory error is thrown.
-XX:GCTimeLimit=95 This limits the proportion of time spent in garbage collection before an OutOfMemory error is thrown. This is used with GCHeapFreeLimit.
-XX:GCHeapFreeLimit=5 This sets the minimum percentage of free space after a full garbage collection before an OutOfMemory error is thrown. This is used with GCTimeLimit.
-XX:InitialHeapSize=3g 設置初始堆空間(年輕區+老年區)
-XX:MaxHeapSize=3g 設置最大堆空間(年輕區+老年區)
-XX:NewSize=128m 設置年輕區的初始空間
-XX:MaxNewSize=128m 設置年輕區的最大空間
-XX:SurvivorRatio=15 設置單個幸存者空間的大小為伊甸園空間大小的一部分
-XX:PermSize=512m 設置永久區的初始空間
-XX:MaxPermSize=512m 設置永久區的最大空間
-Xss512k 設置專用於每個線程的棧區域的大小(以位元組為單位)

GC日誌標記

標記 描述
-verbose:gc or -XX:+PrintGC This prints the basic garbage collection information.
-XX:+PrintGCDetails This will print more detailed garbage collection information.
-XX:+PrintGCTimeStamps You can print timestamps for each garbage collection event. The seconds are sequential and begin from the JVM start time.
-XX:+PrintGCDateStamps You can print date stamps for each garbage collection event.
-Xloggc: Using this you can redirect garbage collection output to a file instead of the console.
-XX:+Print\TenuringDistribution You can print detailed information regarding young space following each collection cycle.
-XX:+PrintTLAB You can use this flag to print TLAB allocation statistics.
-XX:+PrintReferenceGC Using this flag, you can print the times for reference processing (that is, weak, soft, and so on) during stop-the-world pauses.
-XX:+HeapDump\OnOutOfMemoryError This creates a heap dump file in an out-of-memory condition.

總結

  • 對象生命周期分成3個階段,對象創建,對象使用和對象銷毀。
  • 標記-清除、標記-清除-壓縮、標記-複製機制如何工作。
  • 不同的單線程和併發垃圾回收演算法。
  • 直到Java 8, 併發收集器是預設演算法。
  • 從Java 9開始, G1是預設演算法。
  • 此外,還有各種標誌,用於控制垃圾收集演算法的行為並記錄任何應用程式的有用信息

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

-Advertisement-
Play Games
更多相關文章
  • 一、多線程的sleep方法 1.Thread.sleep(毫秒) 2.sleep方法是一個靜態方法 3.該方法的作用:阻塞當前線程,騰出CPU,讓給其他線程 4.sleep的異常註意事項,以及中斷休眠的一種方式及其註意點 package com.bjpowernode.java_learning; ...
  • 最近c艹在學類與對象 擅長划水的我並沒有聽課,害,所以東西有點雲里霧裡, 所以寫下這一篇博客來理解一下。 類的使用就像是封裝一類的東西,定義為一個類 定義的地方和結構體其實還是有點相似的。 這東西在演算法裡面用的感覺不多, 以前也沒接觸過, 現在發現實際運用還是很有意思的。 首先是定義 class C ...
  • Set集合的功能和Collection是一致的。 HashSet:底層數據結構是哈希表,線程非同步。 HashSet保證元素唯一性:hashCode()和equals() 如果元素的hashCode值相同,才會判斷equals是否為true。 如果元素的hashCode值不同,不會調用equals。 ...
  • from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba # 生成詞雲 def create_word_cloud(filename): with open('hongloumong.txt',encod ...
  • 為什麼要寫STL淺談這個系列,因為最近我在準備藍橋杯,刷題的時候經常要用到STL,準備補一補,但一直沒有找到一個好的視頻和資料,最開始準備跟著c語言中文網學,但覺得太繁雜了,最後在b站(b站上電腦類的教學視頻挺多的)上找了一個視頻學的。這個系列相當於我的一個整理。 這個系列只是淺談,但刷題應該夠了 ...
  • 這是我的第一篇隨筆,當然是發我寫的第一個游戲啦! 大一(本人現在大二)寒假過完年,在家待著想起放假前計劃寫一個游戲的,因為本人立志走游戲開發這條路,加上大一上冊學了C語言,就想寫個游戲練練手。想了很久,最後決定寫一個俄羅斯方塊。 萬事開頭難,一開始真的不知道從何下手,所以百度查了一些資料(程式猿必須 ...
  • 1. web.xml中url pattern配置 url pattern為/ 使用SpringMVC的框架時,需要在 配置前端控制器 ,配置為: url pattern為/ 我們需要使用過濾器時,需要在 中進行註冊。以處理中文亂碼的過濾器 為例,配置為: url pattern為 .do 使用Str ...
  • [TOC] pandas可以進行數據輸入和輸出,有以下幾種類型:讀取文本文件及硬碟上其他更高效的格式文件,從資料庫中載入數據,於網路資源進行交互(比如Web API)。 下麵進行不同文本文件的讀取和寫入操作講解,首先進行文本格式數據的讀寫講解。 一:文本格式數據的讀寫 將表格型數據讀取為DataFr ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...