<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # Java 垃圾收集算法(直到 Java 9) > 原文: [https://howtodoinjava.com/java/garbage-collection/all-garbage-collection-algorithms/](https://howtodoinjava.com/java/garbage-collection/all-garbage-collection-algorithms/) **垃圾收集**(GC)一直是 Java 受歡迎的重要特征之一。 垃圾回收是 Java 中用來釋放未使用的內存的機制。 本質上,它是**跟蹤所有仍在使用的對象,并將其余對象標記為垃圾**。 Java 的垃圾回收被認為是一種自動內存管理架構,因為程序員不必將對象指定為可以被重新分配的對象。 垃圾回收在低優先級線程上運行。 在本教程中,我們將介紹與內存分配/解除分配,在后臺運行的算法以及自定義此行為所需的選項有關的各種概念。 ```java Table of Contents Object Life Cycle Garbage collection algorithms Mark and sweep Concurrent mark sweep (CMS) garbage collection Serial garbage collection Parallel garbage collection G1 garbage collection Customization Options Summary ``` ## 對象生命周期 一個 Java 對象的生命周期可以分為三個階段: 1. #### 對象創建 為了[創建對象](https://howtodoinjava.com/puzzles/how-to-create-an-instance-of-any-class-without-using-new-keyword/),通常我們使用`new`關鍵字。 例如 ```java Object obj = new Object(); ``` 創建對象時,將分配特定數量的內存來存儲該對象。 分配的內存量可能會根據架構和 JVM 而有所不同。 2. #### 對象使用 到那時為止,對象被應用程序的其他對象使用(其他活動對象具有指向它的引用)。 在使用過程中,對象駐留在內存中,并且可能包含對其他對象的引用。 3. #### 對象銷毀 垃圾收集系統監視對象,并在可行的情況下計算對每個對象的引用數。 如果沒有對對象的引用,則無法使用當前正在運行的代碼來訪問它,因此取消分配關聯的內存是很有意義的。 ## 垃圾收集算法 對象創建由您編寫的代碼完成; 以及用于使用其提供的特性的框架。 作為 Java 開發人員,我們不需要取消分配內存或取消引用對象。 垃圾收集器會在 JVM 級別自動完成此操作。 自 Java 誕生以來,在算法上進行了大量更新,這些算法在后臺運行以釋放內存。 讓我們看看它們如何工作? #### 標記清除 它是初始且非常基本的算法,分為兩個階段運行: 1. **標記活動對象** – 找出所有仍然存在的對象。 2. **刪除無法訪問的對象** – 擺脫所有其他東西 – 所謂的已死和未使用的對象。 首先,GC 將某些特定對象定義為**垃圾收集根**。 例如當前執行方法的局部變量和輸入參數,活動線程,已加載類的靜態字段和 JNI 引用。 現在,GC 遍歷了內存中的整個對象圖,從這些根開始,然后是從根到其他對象的引用。 GC 訪問的每個對象都被標記為活動對象。 > 需要停止應用程序線程以進行標記,因為如果它不斷變化,它將無法真正遍歷圖。 它被稱為 **Stop The World** 暫停。 第二階段是清除未使用的對象以釋放內存。 這可以通過多種方式來完成,例如 * **正常刪除** – 正常刪除會將未引用的對象刪除以釋放空間并保留引用的對象和指針。 內存分配器(某種哈希表)保存對可分配新對象的可用空間塊的引用。 通常被稱為`mark-sweep`算法。 ![Normal Deletion - Mark and Sweep](https://img.kancloud.cn/07/99/07995ca4373ebb4deefca4bbc940c9a3_596x124.png) 正常刪除 - 標記清除 * **帶有壓縮的刪除** – 僅刪除未使用的對象效率不高,因為可用內存塊分散在整個存儲區域中,并導致[`OutOfMemoryError`](https://docs.oracle.com/javase/9/docs/api/java/lang/OutOfMemoryError.html),如果創建的對象足夠大并且找不到足夠大的內存塊。 為了解決此問題,刪除未引用的對象后,將對其余的引用對象進行壓縮。 這里的壓縮指的是將參考對象一起移動的過程。 這使得新的內存分配變得更加容易和快捷。 通常被稱為`mark-sweep-compact`算法。 ![Deletion with compacting](https://img.kancloud.cn/5b/00/5b00912328a9212c42036c53c36cdd4d_583x156.png) 帶有壓縮的刪除 * **帶有復制的刪除** – 與標記和補圖方法非常相似,因為它們也會重新放置所有活動對象。 重要的區別是重定位的目標是不同的存儲區域。 通常被稱為`mark-copy`算法。 ![Deletion with copying - Mark and Sweep](https://img.kancloud.cn/f6/20/f6204cd8580c94a6aad799819ac6f0ca_583x131.png) 帶有復制的刪除 – 標記清除 在進一步閱讀之前,我將真誠地建議您首先閱讀[ java 內存管理](https://howtodoinjava.com/java/garbage-collection/revisiting-memory-management-and-garbage-collection-mechanisms-in-java/)。 它詳細討論了新生代,老年代和永久代。 #### 并發標記清除(CMS)垃圾收集 CMS 垃圾回收實質上是一種升級的標記和清除方法。 它使用多個線程掃描堆內存。 對其進行了修改,以利用更快的系統并增強了性能。 它嘗試通過與應用程序線程同時執行大多數垃圾收集工作來最大程度地減少由于垃圾收集而造成的暫停。 它在新生代中使用并行的**標記復制**算法,在老一代中使用大多數并發的**標記清除**算法。 要使用 CMS GC,請使用以下 JVM 參數: ```java -XX:+UseConcMarkSweepGC ``` ###### CMS GC 優化選項 | 標志 | 描述 | | --- | --- | | `-XX:+UseCMSInitiating\OccupancyOnly` | 表示您只想使用占用率作為啟動 CMS 收集操作的條件。 | | `-XX:CMSInitiating\OccupancyFraction=7` | 設置 CMS 生成占用率以啟動 CMS 收集周期。 | | `-XX:CMSTriggerRatio=70` | 這是在 CMS 周期開始之前分配的 CMS 生成中`MinHeapFreeRatio`的百分比。 | | `-XX:CMSTriggerPermRatio=90` | 設置在開始 CMS 收集周期之前已分配的 CMS 永久代中`MinHeapFreeRatio`的百分比。 | | `-XX:CMSWaitDuration=2000` | 使用參數指定允許 CMS 等待年輕集合的時間。 | | `-XX:+UseParNewGC` | 選擇使用并行算法收集年輕空間。 | | `-XX:+CMSConcurrentMTEnabled` | 允許在并發階段使用多個線程。 | | `-XX:ConcGCThreads=2` | 設置用于并發階段的并行線程數。 | | `-XX:ParallelGCThreads=2` | 設置要用于 STW 階段的并行線程數。 | | `-XX:+CMSIncrementalMode` | 啟用增量 CMS(iCMS)模式。 | | `-XX:+CMSClassUnloadingEnabled` | 如果未啟用此特性,CMS 將不會清除永久空間。 | | `-XX:+ExplicitGCInvokes\Concurrent` | 這允許`System.gc()`觸發并發收集,而不是整個垃圾收集周期。 | #### 串行垃圾收集 該算法為新生代使用*標記復制*,為老一代使用*標記掃描壓縮*。 它在單個線程上工作。 執行時,它將凍結所有其他線程,直到垃圾回收操作結束。 由于串行垃圾回收具有線程凍結特性,因此僅適用于非常小的程序。 要使用串行 GC,請使用以下 JVM 參數: ```java -XX:+UseSerialGC ``` #### 并行垃圾收集 是串行 GC 類似,在新生代中使用`mark-copy`,在老一代中使用`mark-sweep-compact`。 多個并發線程用于標記和復制/壓縮階段。 您可以使用`-XX:ParallelGCThreads=N`選項配置線程數。 如果您的主要目標是通過有效利用現有系統資源來提高吞吐量,那么并行垃圾收集器將適用于多核計算機。 使用這種方法,可以大大減少 GC 循環時間。 直到 Java 8,我們都將并行 GC 視為默認的垃圾收集器。 從 Java 9 始,G1 是 32 位和 64 位服務器配置上的默認垃圾收集器。– [JEP 248](https://openjdk.java.net/jeps/248) 要使用并行 GC,請使用以下 JVM 參數: ```java -XX:+UseParallelGC ``` #### G1 垃圾收集 G1(垃圾優先)垃圾收集器已在 Java 7 中提供,旨在長期替代 CMS 收集器。 G1 收集器是并行的,并發的,漸進壓縮的低暫停垃圾收集器。 此方法涉及將內存堆分段為多個小區域(通常為 2048)。 每個區域都被標記為新生代(進一步劃分為伊甸園地區或幸存者地區)或老一代。 這樣,GC 可以避免立即收集整個堆,而可以逐步解決問題。 這意味著一次只考慮區域的一個子集。 ![Memory regions marked - G1](https://img.kancloud.cn/52/aa/52aa92f11612c412e67b31f0f1e3b16a_520x207.png) 標記為 – G1 的內存區域 G1 跟蹤每個區域包含的實時數據量。 此信息用于確定包含最多垃圾的區域。 因此它們是首先收集的。 這就是為什么將其命名為**垃圾優先**集合的原因。 與其他算法一樣,不幸的是,壓縮操作是使用 *Stop the World* 方法進行的。 但是,根據設計目標,您可以為其設置特定的性能目標。 您可以配置暫停持續時間,例如在任何給定的秒內不超過 10 毫秒。 垃圾優先 GC 將盡最大可能(但不能確定,由于 OS 級線程管理,這很難實時實現)來盡力實現該目標。 如果要在 Java 7 或 Java 8 計算機中使用,請使用 JVM 參數,如下所示: ```java -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` | 這是用于限制在拋出`OutOfMemory`錯誤之前在垃圾回收上花費的時間的使用策略。 | | `-XX:GCTimeLimit=95` | 這限制了在引發`OutOfMemory`錯誤之前在垃圾回收上花費的時間比例。 與`GCHeapFreeLimit`一起使用。 | | `-XX:GCHeapFreeLimit=5` | 這設置了在拋出`OutOfMemory`錯誤之前,在進行完全垃圾回收之后的最小可用空間百分比。 與`GCTimeLimit`一起使用。 | | `-XX:InitialHeapSize=3g` | 設置初始堆大小(年輕空間加上租用空間)。 | | `-XX:MaxHeapSize=3g` | 設置最大堆大小(年輕空間加租用空間)。 | | `-XX:NewSize=128m` | 設置年輕空間的初始大小。 | | `-XX:MaxNewSize=128m` | 設置年輕空間的最大大小。 | | `-XX:SurvivorRatio=15` | 將單個幸存者空間的大小設置為 Eden 空間大小的一部分。 | | `-XX:PermSize=512m` | 設置永久空間的初始大小。 | | `-XX:MaxPermSize=512m` | 設置永久空間的最大大小。 | | `-Xss512k` | 設置每個線程專用的棧區域的大小(以字節為單位)。 | #### GC 記錄標志 | 標志 | 描述 | | --- | --- | | `-verbose:gc or -XX:+PrintGC` | 這將打印基本的垃圾收集信息。 | | `-XX:+PrintGCDetails` | 這將打印更詳細的垃圾收集信息。 | | `-XX:+PrintGCTimeStamps` | 您可以為每個垃圾收集事件打印時間戳。 這些秒是連續的,并且從 JVM 啟動時間開始。 | | `-XX:+PrintGCDateStamps` | 您可以為每個垃圾收集事件打印日期戳。 | | `-Xloggc:` | 使用此方法,您可以將垃圾回收輸出重定向到文件而不是控制臺。 | | `-XX:+Print\TenuringDistribution` | 您可以在每個收集周期之后打印有關年輕空間的詳細信息。 | | `-XX:+PrintTLAB` | 您可以使用此標志來打印 TLAB 分配統計信息。 | | `-XX:+PrintReferenceGC` | 使用此標志,您可以打印世界暫停期間進行參考處理的時間(即弱,弱等)。 | | `-XX:+HeapDump\OnOutOfMemoryError` | 這將在內存不足的情況下創建堆轉儲文件。 | ## 總結 因此,在此 **Java 垃圾回收教程**中,我們學習了以下內容: 1. 對象生命周期分為三個階段,即對象創建,對象使用和對象銷毀。 2. `mark-sweep`,`mark-sweep-compact`和`mark-copy`機制如何運作。 3. 不同的單線程和并發 GC 算法。 4. 直到 Java 8,并行 GC 才是默認算法。 5. 從 Java 9 開始,將 G1 設置為默認 GC 算法。 6. 此外,還有各種標志來控制垃圾收集算法的行為并記錄任何應用程序的有用信息。 將我的問題放在評論部分。 學習愉快!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看