日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM学习笔记(四)

發布時間:2024/9/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM学习笔记(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JVM學習筆記(四)

文章目錄

  • JVM學習筆記(四)
    • 筆記鏈接
    • 1.GC算法
      • 1.1GC-判斷對象是否可回收
        • 1.1.1 引用計數法
        • 1.1.1 可達性分析
      • 1.2GC-回收算法
        • 標記清除法(Mark-Sweep)
        • 標記整理法(Mark-Compact)
        • 復制算法(copy)
        • 1.2.1 分代收集算法(重點)
          • 1. 新生代和復制算法
          • 2. 老年代與標記整理算法
        • 分區收集算法
    • 2.GC垃圾收集器
      • 2.1 垃圾收集器的種類
      • 2.2 Serial垃圾收集器
      • 2.3 ParNew垃圾收集器
      • 2.4 Parallel Scavenge 收集器
      • 2.5 Serial Old收集器
      • 2.6 Parallel Old收集器
      • 2.7 CMS 收集器
      • 2.8 G1收集器

筆記鏈接

JVM學習筆記(一)
JVM學習筆記(二)
JVM學習筆記(三)
JVM學習筆記(四)

(待更新…)

1.GC算法

1.1GC-判斷對象是否可回收

1.1.1 引用計數法

? 在 Java 中,引用和對象是有關聯的。顯然引用計數法,即一個對象如果沒有任何與之關聯的引用,即他們的引用計數為 0,則說明對象不太可能再被用到,那么這個對象就是可回收對象。

方案: 給對象維護一個引用計數器,當有一個地方引用到它,則計數器加1,當有引用失效,則計數器減1,當為0時,說明沒有地方引用到這個對象。

  • 優點: 實現簡單、效率高
  • 缺點: 無法解決循環引用。(致命缺點)

循環引用問題: 假設棧中有兩引用A,B,對應堆中的對象分別為a,b,而對象a,b中有相互指向的引用C和D,現在A=null,B=null,棧中已經沒有引用指向對象a和b,但對象中C和D引用相互指向,所以a,b無法釋放。

如圖效果:

1.1.1 可達性分析

為了解決引用計數法的循環引用問題,Java 使用了可達性分析的方法。

通過一系列的“GC roots”對象作為起點搜索。如果在“GC roots”和一個對象之間沒有可達路徑,則稱該對象是不可達的。要注意的是,不可達對象不等價于可回收對象,不可達對象變為可回收對象至少要經過兩次標記過程。兩次標記后仍然是不可達對象,則將面臨回收。

圖片:

圖中的a,b對象將會被回收。

1.2GC-回收算法

標記清除法(Mark-Sweep)

法如其名,分為兩個階段,標注和清除。標記階段標記出所有需要回收的對象,清除階段回收被標記的對象所占用的空間。

  • 缺點: 內存碎片化。

如圖:

標記整理法(Mark-Compact)

標記階段和 Mark-Sweep 算法相同,標記后不是清理對象,而是將存活對象移向內存的一端。然后清除端邊界外的對象。

如圖:

復制算法(copy)

按內存容量將內存劃分為等大小的兩塊。每次只使用其中一塊,當這一塊內存滿后將尚存活的對象復制到另一塊上去,把已使用的內存清掉。回顧:GC中minor GC用的算法。

  • 優點: 內存效率高,不易產生碎片

  • 缺點: 浪費一定量的空間(要找地方放復制的對象)

圖片:

1.2.1 分代收集算法(重點)

現在絕大部分的JVM在使用的算法,其實就是根據堆的老年代和新生代而劃分使用上面三種GC中的某幾種。老生代的特點是每次垃圾回收時只有少量對象需要被回收,新生代的特點是每次垃圾回收時都有大量垃圾需要被回收,因此可以根據不同區域選擇不同的算法。

1. 新生代和復制算法

新生代通常使用復制算法,From和To區域就是這樣來的,以為復制算法需要交換區來保存存活對象。為新生代中每次垃圾回收都要回收大部分對象,即要復制的操作比較少,但通常并不是按照 1:1 來劃分新生代。而是按照8:1:1來劃分(這個是HotSpot虛擬機的默認比例)。o( ̄▽ ̄)ブ,來回顧一下前面的筆記:

由于頻繁創建對象,所以新生代會頻繁觸發MinorGC 進行垃圾回收。當 Eden 區內存不夠的時候就會觸發 MinorGC,對新生代區進行一次垃圾回收。MinorGC使用的是復制算法,過程如下:

  • MinorGC會把Eden Space+From Space掃描一邊
  • 掃描過后將存活的對象復制到 To Space 區域,并對對象的年齡進行+1
  • 然后清空Eden Space+From Space的對象
  • 最后,將To Space和From Space標志互換(不移動對象,區域的標志更換,就是To變成From),To Space等待下次MinorGC的回收。
  • 2. 老年代與標記整理算法

    老年代因為每次只回收少量對象,因而一般采用 Mark-Compact 算法。老樣子回顧一下,這次整合一下:

  • MinorGC會把Eden Space+From Space掃描一邊
  • 掃描過后將存活的對象復制到 To Space 區域,并對對象的年齡進行+1
  • 然后清空Eden Space+From Space的對象
  • 最后,將To Space和From Space標志互換(不移動對象,區域的標志更換,就是To變成From),To Space等待下次MinorGC的回收。
  • 當老年區滿了以后(一般以為MinorGC后存活的對象無法放到老年區),垃圾回收器會對老年區進行清理。
  • 標記老年區中的存活對象后,將存活對象移向內存的一端。
  • 然后清除端邊界外的對象。
  • 分區收集算法

    分區算法則將整個堆空間劃分為連續的不同小區間, 每個小區間獨立使用, 獨立回收.。

    2.GC垃圾收集器

    ? 堆內存被劃分為新生代和年老代兩部分,新生代主要使用復制和標記-清除垃圾回收算法;年老代主要使用標記-整理垃圾回收算法,因此 java 虛擬中針對新生代和年老代分別提供了多種不同的垃圾收集器。垃圾回收器是GC的執行者,所以前面的筆記并沒有特別說明Full GC和Major GC是指定用那種算法進行回收,其實不同垃圾回收器對不同的區域進行垃圾回收,而且不同垃圾回收器使用的算法并不完全一致。下面我就要介紹垃圾回收器的種類。o( ̄▽ ̄)ブ

    2.1 垃圾收集器的種類

    垃圾回收器主要分三大類:

    • 新生代收集器:Serial、ParNew、Parallel Scavenge
    • 老年代收集器:CMS、Serial Old、Parallel Old
    • 整堆收集器: G1

    HotSpot JVM (JDK1.6)的垃圾回收器情況圖

    2.2 Serial垃圾收集器

    Serial是最基本垃圾收集器,Serial使用的算法和線程類型如下:

    • 算法: 復制算法
    • 線程: 單線程
    • 區域: 新生代

    Serial 是一個單線程的收集器,**在進行垃圾收集的同時,必須暫停其他所有的工作線程,直到垃圾收集結束。(多CPU下也如此)**Serial 垃圾收集器雖然在收集垃圾過程中需要暫停所有其他的工作線程,但是它簡單高效,對于限定單個 CPU 環境來說,沒有線程切換的開銷。單核單CPU的情況下可以獲得最高的單線程垃圾收集效率。

    Serial和Serial Old執行過程如下圖:

    2.3 ParNew垃圾收集器

    ? ParNew 垃圾收集器其實是 Serial 收集器的多線程版本,也使用復制算法,除了使用多線程進行垃圾收集之外,其余的行為和 Serial 收集器完全一樣。

    • 算法: 復制算法
    • 線程: 多線程
    • 區域: 新生代

    ParNew 收集器默認開啟和 CPU 數目相同的線程數,可以通過下面JVM參數調節

    -XX:ParallelGCThreads

    ParNew垃圾收集器是很多 java虛擬機運行在 Server 模式下新生代的默認垃圾收集器。

    2.4 Parallel Scavenge 收集器

    Parallel Scavenge 收集器也是一個新生代垃圾收集器,在垃圾收集過程中也是需要暫停所有的工作線程有以下特點:

    • 算法: 復制算法
    • 線程: 多線程
    • 調節策略: 自適應調節策略(根據吞吐量控制)
    • 區域: 新生代

    Parallel Scavenge是一種非常高效的垃圾收集器,它使用吞吐量來控制垃圾回收的時間,吞吐量公式如下:

    吞吐量=運行用戶代碼shi間運行用戶代碼時間+垃圾收集時間吞吐量=\frac{運行用戶代碼shi間}{運行用戶代碼時間+垃圾收集時間} =+shi?

    高吞吐量可以最高效率地利用 CPU 時間,盡快地完成程序的運算任務,主要適用于在后臺運算而不需要太多交互的任務。Parallel Scavenge追求的是高吞吐量。自適應調節策略也是 ParallelScavenge 收集器與 ParNew 收集器的一個重要區別。

    2.5 Serial Old收集器

    Serial Old 是 Serial 垃圾收集器年老代版本,老年代一般使用標志整理算法(Mark-compact),跟Serial 垃圾收集器一樣,是單線程,也一樣要停掉其他線程的運行。運行在 Serial Old是Client 默認的 java 虛擬機默認的老年代垃圾收集器,跟Serial不同,Serial是Client 默認的 java 虛擬機默認的新生代垃圾收集器。

    • 算法: 標志整理算法
    • 線程: 單線程
    • 區域: 老年代

    Serial和Serial Old執行過程如下圖:

    2.6 Parallel Old收集器

    從名字上就知道,Parallel Old 收集器是Parallel Scavenge的年老代版本,行為上跟Parallel Scavenge基本一樣,而算法不同。Parallel Old 正是為了在年老代同樣提供吞吐量優先的垃圾收集器。

    • 算法: 標志整理算法
    • 線程: 多線程
    • 區域: 老年代
    • 提供時間: JDK1.6

    Parallel Scavenge 和Parallel Old 搭配運行過程圖:

    2.7 CMS 收集器

    Concurrent mark sweep(CMS)收集器是老年代垃圾收集器,主要目標是獲取最短垃圾回收停頓時間,使用的算法跟其他老年代的垃圾收集器有所不同,使用的是標記清除算法。一般用在一些交互比較高的程序,最短時間的停頓,能有效確保交互程序和用戶交互的體驗。

    • 算法: 標志清除算法
    • 線程: 多線程
    • 區域: 老年代

    CMS工作機制:

  • 初始標記:只是標記一下 GC Roots 能直接關聯的對象,速度很快,但暫停所有的工作線程。
  • 并發標記:進行 GC Roots 跟蹤的過程,和用戶線程一起工作。
  • 重新標記:為了修正在并發標記期間,因用戶程序繼續運行而導致標記產生變動的那一部分對象的標記記錄,仍然需要暫停所有的工作線程。
  • 并發清除:清除 GC Roots 不可達對象,和用戶線程一起工作,不需要暫停工作線程。
  • 各階段的耗時:

    • 初始標記:耗時短(簡易標志,速度快)
    • 并發標記:耗時較長(跟蹤)
    • 重新標記:耗時短(補全并發標記時,程序變化的那部分,標記量小)
    • 并發清除:耗時較長(清除)

    結論:總體上來看CMS 收集器的內存回收和用戶線程是一起并發地執行。

    工作過程圖:

    2.8 G1收集器

    Garbage First(G1)是垃圾收集領域的最新成果,同時也是HotSpot在JVM上力推的垃圾收集器,并賦予取代CMS的使命。

    找到兩篇很好的博客
    https://blog.csdn.net/renfufei/article/details/41897113.

    https://blog.csdn.net/coderlius/article/details/79272773.

  • G1的設計原則是"首先收集盡可能多的垃圾(Garbage First)"。因此,G1并不會等內存耗盡(串行、并行)或者快耗盡(CMS)的時候開始垃圾收集,而是在內部采用了啟發式算法,在老年代找出具有高收集收益的分區進行收集。同時G1可以根據用戶設置的暫停時間目標自動調整年輕代和總堆大小,暫停目標越短年輕代空間越小、總空間就越大;
  • G1采用內存分區(Region)的思路,將內存劃分為一個個相等大小的內存分區,回收時則以分區為單位進行回收,存活的對象復制到另一個空閑分區中。由于都是以相等大小的分區為單位進行操作,因此G1天然就是一種壓縮方案(局部壓縮);
  • G1雖然也是分代收集器,但整個內存分區不存在物理上的年輕代與老年代的區別,也不需要完全獨立的survivor(to space)堆做復制準備。G1只有邏輯上的分代概念,或者說每個分區都可能隨G1的運行在不同代之間前后切換;
  • G1的收集都是STW的,但年輕代和老年代的收集界限比較模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年輕代分區(年輕代收集),也可能在收集年輕代的同時,包含部分老年代分區(混合收集),這樣即使堆內存很大時,也可以限制收集范圍,從而降低停頓。
    . G1雖然也是分代收集器,但整個內存分區不存在物理上的年輕代與老年代的區別,也不需要完全獨立的survivor(to space)堆做復制準備。G1只有邏輯上的分代概念,或者說每個分區都可能隨G1的運行在不同代之間前后切換;
  • G1的收集都是STW的,但年輕代和老年代的收集界限比較模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年輕代分區(年輕代收集),也可能在收集年輕代的同時,包含部分老年代分區(混合收集),這樣即使堆內存很大時,也可以限制收集范圍,從而降低停頓。
  • 總結

    以上是生活随笔為你收集整理的JVM学习笔记(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。