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使用的是復制算法,過程如下:
2. 老年代與標記整理算法
老年代因為每次只回收少量對象,因而一般采用 Mark-Compact 算法。老樣子回顧一下,這次整合一下:
分區收集算法
分區算法則將整個堆空間劃分為連續的不同小區間, 每個小區間獨立使用, 獨立回收.。
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:ParallelGCThreadsParNew垃圾收集器是很多 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工作機制:
各階段的耗時:
- 初始標記:耗時短(簡易標志,速度快)
- 并發標記:耗時較長(跟蹤)
- 重新標記:耗時短(補全并發標記時,程序變化的那部分,標記量小)
- 并發清除:耗時較長(清除)
結論:總體上來看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雖然也是分代收集器,但整個內存分區不存在物理上的年輕代與老年代的區別,也不需要完全獨立的survivor(to space)堆做復制準備。G1只有邏輯上的分代概念,或者說每個分區都可能隨G1的運行在不同代之間前后切換;
總結
以上是生活随笔為你收集整理的JVM学习笔记(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 客户电脑买来才一年客户电脑买来才一年就坏
- 下一篇: 模拟洗牌小游戏