關於JVM,你必須知道的這些知識點
一、一些必知引數
堆的分配引數
- -Xmx:堆記憶體的最大大小(max)
- -Xms:堆記憶體的初始大小(start)
- -Xmn:新生代大小(new)
- -XX:NewRatio
老年代和新生代(eden+2*s)的比值
例如:4,表示老年代:新生代=4:1,即新生代佔整個堆的1/5 - -XX:SurvivorRatio(Survivor)
設定新生代eden區與Survivor區的比值
例如:8,表示 eden:s0:s1 = 8:1:1,即一個Survivor佔年輕代的1/10
棧的分配引數
棧的分配引數
- -Xss
設定棧空間的大小,通常只有幾百K。決定了函式呼叫的深度
舉例
-Xmx800M –Xms800M –Xmn300M -Xss256K
堆的大小 = 新生代大小 + 老年代大小,上例中最大堆記憶體為 800M,初始堆記憶體為 800M,新生代堆記憶體為 300M,棧空間大小為 256K
二、JVM記憶體分配機制
JVM物件分配邏輯順序如下圖
JVM給物件分配記憶體時,一般都是分配到eden的。但是由於JVM配置的不同,以及一些優化措施,可能會有一些特殊的邏輯,如:棧上分配、TLAB分配、直接進入老年代等。
1. 棧上分配
什麼是棧上分配?為什麼會有棧上分配?
棧上分配是JVM的一種優化技術,基本思想是對於那些執行緒私有
的物件,可以將它們打散分配
在棧上,而不是分配在堆上。
好處:可以在函式呼叫結束後自行銷燬,而不需要垃圾回收器的介入,從而提高系統的效能。
技術基礎: 逃逸分析
和 標量替換
(允許將物件根據屬性打散後分配在棧上)
2. TLAB
什麼是TLAB?為什麼會有TLAB?
TLAB:Thread Local Allocation Buffer(執行緒本地分配快取)是執行緒私有的堆空間
在堆上分配記憶體時,由於堆是執行緒共享的,容易發生衝突(儘管可以使用CAS進行同步,但是仍然可能失敗重試很多次)。所以可以優化使用執行緒自己的TLAB來嘗試分配物件,這樣可以儘可能避免執行緒同步
3. 老年代的物件來源
- 很大的物件,新生代放不下
JVM引數:-XX:PretenureSizeThreshold
,預設為3145728,即 3M - 長期存活的物件
JVM通過物件年齡判斷哪些物件需要晉升到老年代。
JVM引數:-XX:MaxTenuringThreshold
,預設為 15 - 符合動態物件年齡判定規則的物件
JVM並非 “固執” 的要求物件年齡必須達到MaxTenuringThreshold
才能晉升到老年代,如果:
Survivor空間
相同年齡所有物件的大小總和 >Survivor空間
的一半
則:
物件年齡 >= 該年齡的物件 就可以 直接晉升到老年代這樣做,相當於將Survivor空間一半的空間釋放出來了,減少了這些物件在Survivor空間間的來回挪騰
三、垃圾回收
1. 垃圾識別演算法
- 引用計數法
- 可達性分析演算法
- GC Roots物件種類:
- 虛擬機器棧中本地變數表引用的物件
- 方法區中,類靜態變數/常量引用的物件
- 本地方法棧中JNI(Native方法)引用的物件
- GC Roots物件種類:
如何記憶GC Roots節點種類?
其實可以回憶一下Java執行時資料區。
- 程式計數器顯然無法作為根節點
- 堆是我們要進行垃圾回收的區域
因此就只剩下虛擬機器棧、本地方法棧和方法區這三個地方了。
圖為Java執行時資料區
引用的型別有哪些?什麼時候需要回收?
Java將引用分為四種型別,分別如下(強度遞減):
- 強引用 (Strong Reference)
- 最常用的引用型別,預設宣告的物件為強引用,如:Object obj = new Object();
- 使用上述的垃圾識別演算法(可達性分析演算法)進行是否是垃圾、是否要被回收
- 軟引用 (Soft Reference)
- 有用但非必需的物件,常用作快取
- 當在記憶體不足時,就會回收(拋OutOfMemoryError異常之前)
- 弱引用(Weak Reference)
- 非必需的物件
- 無論記憶體是否足夠,GC執行緒都會回收
- 虛引用(Phantom Reference)
- 任何時候都能被回收,主要用來接收GC的通知
垃圾分代回收型別
- Minor GC
發生在新生代的GC,比較頻繁,回收速度也較快 - Major GC/Full GC
發生在老年代的GC,一般同時會伴隨著至少一次的新生代的GC(Minor GC)。回收速度較慢分配擔保機制是什麼?
當發生在Minor GC之前,JVM會進行檢查記憶體空間是否足夠,預設使用老年代的空間作為記憶體分配的擔保。
但是如果:
老年代連續可用空間 < 新生代物件總大小 且 老年代連續可用空間 < 歷次晉升的連續大小
則會先進行Full GC,清理釋放老年代空間。
分配擔保機制的意義在於,保證Minor GC後有記憶體可以分配
2. 垃圾回收演算法
- 標記-清除演算法
- 複製回收演算法
- 標記-整理演算法
3. 垃圾收集器
常見垃圾收集器
有連線代表可以配合使用
常見垃圾收集器工作流程
速記
-
新生代
- Serial:
- 使用複製回收演算法
- STW時,單執行緒進行回收(STW:Stop The World)
- ParNew:
- 使用複製回收演算法
- STW時,多執行緒進行回收
- Parallel Scavenge(全域性):
- 使用複製回收演算法
- 關注吞吐量,即 CPU的使用效率,而不是單純的STW時間長短,適合於後臺任務型程式
- 吞吐量 = 執行使用者程式碼時間 / (執行使用者程式碼時間 + 垃圾收集時間)
- Serial:
-
老年代
- CMS:
-
使用標記-清除演算法
-
重點:減少回收停頓時間
-
收集過程:
① 初始標記(CMS initial mark)
② 併發標記(CMS concurrenr mark)
③ 重新標記(CMS remark)
④ 併發清除(CMS concurrent sweep)其中初始標記、重新標記這兩個步驟任然需要停頓其他使用者執行緒。初始標記僅僅只是標記出GC ROOTS能直接關聯到的物件,速度很快,併發標記階段是進行GC ROOTS 根搜尋演算法階段,會判定物件是否存活。而重新標記階段則是為了修正併發標記期間,因使用者程式繼續執行而導致標記產生變動的那一部分物件的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比並發標記階段要短。
由於整個過程中耗時最長的併發標記和併發清除過程中,收集器執行緒都可以與使用者執行緒一起工作,所以整體來說,CMS收集器的記憶體回收過程是與使用者執行緒一起併發執行的。
-
- Serial Old:
- 使用標記-整理演算法
- 是CMS備用方案,在Concurrent Mode Failure時使用(CMS垃圾回收時,但老年代空間不足)
- Parallel Old:
- 使用標記-整理演算法
- 與Parallel Scavenge配合使用,關注吞吐量
- CMS:
-
G1收集器
- 將整個Java堆劃分為多個大小相等的獨立區域(Region),新生代和老年代不再是物理隔離的了
- 從整體來看是基於“標記-整理”演算法,但從區域性來看是基於“複製“演算法
- 收集過程:
① 初始標記(Initial Marking)
② 併發標記(Concurrent Marking)
③ 最終標記(Final Marking)
④ 篩選回收(Live Data Counting and Evacuation)
4. GC日誌怎麼看
Minor GC日誌
Full GC日誌
5. 監控
JDK自帶的監控工具
- jmap -heap pid 堆使用情況
- jstat -gcutil pid 1000
- jstack 執行緒dump
- jvisualvm
- jconsole
官方說明:
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/toc.html
相關文章
- 關於Flutter 您必須知道的知識點!!!Flutter
- 關於Mysql事務,你必須知道的幾個知識點!MySql
- 關於索引必須知道的知識索引
- 程式猿必須知道的關於 Tomcat 的知識點Tomcat
- 這些關於WebSocket的知識,你知道多少?Web
- 關於Linux作業系統,這些你必須知道!Linux作業系統
- 大學期間必須知道的JVM知識JVM
- 你必須知道的Java基礎知識Java
- 關於 Laravel 資料庫查詢鎖必須要知道的知識點Laravel資料庫
- Netty中的這些知識點,你需要知道!Netty
- 關於資料庫索引,必須掌握的知識點資料庫索引
- JVM-Java工程師必須掌握的知識點JVMJava工程師
- Nacos必知必會:這些知識點你一定要掌握!
- 關於美顏SDK,還有這些你不知道的知識
- Python入門必須知道的11個知識點Python
- 初學Python必須知道的11個知識點!Python
- 關於ES模組你必須要知道的一些禁忌(一)
- 你需要知道這些關於技術美術的知識構成
- 關於Http協議,你必須要知道的HTTP協議
- 這三個關於Python包匯入的知識點你知道嗎Python
- 這三個關於Python包匯入的知識點你知道嗎?Python
- 遊戲出海越南前,這些事情你必須知道遊戲
- 千萬淘寶店運營必備知識,你必須知道!
- 軟體工程師必須知道20個知識點你瞭解多少?軟體工程工程師
- Python爬蟲需要學哪些東西?這些知識點必須掌握!Python爬蟲
- 前端必須掌握的知識點前端
- 理解大型分散式網站你必須知道這些概念分散式網站
- Linux系統擁有哪些特性?這些你必須知道!Linux
- 對於MySQL你必須要了解的鎖知識MySql
- Java 異常你必須瞭解的一些知識Java
- 面試官帶你學Android——面試中Handler 這些必備知識點你都知道嗎?面試Android
- 做iOS自動化測試必須知道的一些知識iOS
- 關於移動端適配,你必須要知道的
- 作為一個程式設計師,CPU的這些硬核知識你必須會!程式設計師
- 想要學習Python課程,這些問題你必須知道!Python
- CSS你可以不寫,但這些規範必須要知道!CSS
- 關於雲原生,這些你要知道
- 關於深度學習,這些知識點你需要了解一下深度學習