【譯】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
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...