總體介紹
JVM內存結構
JVM體系概述
Java8以後的JVM
GC作用域
常見的垃圾回收算法
引用計數
複製算法
標記清除
標記整理
JM垃圾回收的時候如何確定垃圾?什麼是 GC Roots
什麼是垃圾
簡單的說就是內存中已經不再被使用到的空間就是垃圾
要進行垃圾回收,如何判斷一個對象是否可以被回收
引用計數法
Java中,引用和對象是有關聯的。如果要操作對象則必須用引用進行
因此,很顯然一個簡單的辦法是通過引用計數來判斷一個對象是否可以回收。簡單說,給對象中添加一個引用計數器,
每當有一個地方引用它,計數器值加1
每當有一個引用失效時,計數器值減1。
任何時刻計數器值爲零的對象就是不可能再被使用的,那麼這個對象就是可回收對象
那爲什麼主流的Java虛擬機裏面都沒有選用這種算法呢?其中最主要的原因是它很難解決對象之間相互循環引用的問題
枚舉根節點做可達性分析(根搜索路徑)
demo
java 可以做GCRoots的對象
- 虛擬機棧(棧幀中的局部變量區,也叫做局部變量表
- 方法區中的類靜態屬性引用的對象。
- 方法區中常量引用的對象
- 本地方法棧中N( Native方法)引用的對象
JVM調優和參數配置,如何盤點查看MM系統默認值
JVM的參數類型
標配參數
X參數(瞭解)
-Xint 解釋執行
-Xcomp 第一次使用就編譯成本地代碼
-Xmixed 混合模式
XX參數
Boolean類型
公式
-XX:+或者- 某個屬性值
+表示開啓 -表示關閉
是否打印GC收集細節
-XX:+PrintGCDetails
-XX:-PrintGCDetails
是否使用串行垃圾收集器
-XX:-UseSerialGC
-XX:+UseSerialGC
KV設值類型
公式
-XX:屬性key=屬性值value
-XX:MetaspaceSize=128m
-XX:MaxTenuringThreshold=15
jinfo舉例,如何查看當前運行程序的配置
公式
jinfo -flag 配置項 進程編號
題外話(坑題)
兩個經典參數:-Xms和-Xmx
-Xms <===>等價於 -XX:InitialHeapSize
-Xmx <====>等價於-XX:MaxHeapSize
查看JVM默認值
-XX:+PrintFlagsInitial
查看初始默認值
公式
java -XX:+PrintFlagsInitial -version
java -XX:+PrintFlagsInitial
常用的JVM基本配置參數有哪些
常用參數
-Xms
初始大小內存,默認爲物理內存1/64
等價於-XX:InitialHeapSize
-Xmx
最大分配內存,默認爲物理內存1/4
等價於-XX:MaxHeapSize
-Xss
設置單個線程的大小,一般默認爲512K~1024K
等價於-XX:ThreadStackSize
-Xmn
設置年輕代大小
-XX:MetaspaceSize
設置元空間大小
元空間的本質和永久代類似,都是對JVM規範中方法區的實現,不過元空間與永久代之間最大的區別在於;元空間並不在虛擬機中,而是使用本地內存。因此,默認情況下,源空間的大小僅受本地內存限制。
-Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal
設置案例
-XX:+PrintGCDetails
輸出詳細GC收集日誌信息
GC
FullGC
-XX:SurvivoRatio
-XX:NewRatio
-XX:MaxTenuringThreshold
設置垃圾最大年齡
強引用、軟引用、弱引用、虛引用分別
整體架構
強引用(默認支持模式)
軟引用
弱引用
軟引用和弱應用的適用場景
虛引用
GCRoots和四大引用的小總結
對OOM的認識
Java.lang.StackOverflowError
遞歸調用 棧的大小默認爲512K~1024K
Java.lang.OutOfMemoryError:Java heap space
Java.lang.OutOfMemeoryError:GC overhead limit exceeded
程序在垃圾回收上花費了98%的時間,卻收集不回2%的空間,通常這樣的異常伴隨着CPU的衝高
Java.lang.OutOfMemeoryError:Direct buffer memory
Java.lang.OutOfMemeoryError:unable to create new native thread
Java.lang.OutOfMemeoryError:Metaspace
-XX:+PrintFlagsInitial命令查看本機的初始化參數,-XX:MetaspaceSize爲21810376B(約20M)
GC垃圾回收算法和垃圾收集器的關係
GC算法(引用計數/複製/標清/標整)是內存回收的方法論,垃圾收集器就是算法落地實現
因爲目前爲止還沒有完美的收集器出現,更加沒有萬能的收集器,只是針對具體應用最合適的收集器,進行分代收集
4種主要垃圾收集器
串行垃圾回收器(Serial)
它爲單線程環境設計並且只使用一個線程進行垃圾回收,會暫停所有的用戶線程。所以不適合服務器環境
並行垃圾回收器(Parallel)
多個垃圾回收線程並行工作,此時用戶線程是暫停的,適用於科學計算/大數據處理等弱交互場景
併發垃圾回收器(CMS)
用戶線程和垃圾收集線程同時執行(不一定是並行,可能交替執行),不需要停頓用戶線程
互聯網公司多用它,適用於對響應時間有要求的場景
G1垃圾回收器
G1垃圾回收器將堆內存分割成不同的區域然後併發的對其進行垃圾回收
怎麼查看服務器默認的垃圾收集器是那個?生產上如何配置垃圾收集器的?
怎麼查看默認的垃圾收集器是哪個?
java -XX:+PrintCommandLineFlags -version
默認的垃圾收集器有哪些
垃圾收集器
部分參數預先說明
Server/Client模式分別是什麼意思
新生代
串行GC(Serial)/(Serial Coping)
並行GC(ParNew)
並行回收GC(Parallel)/(Parallel Scavenge)
老年代
串行回收GC(Serial Old)/(Serial MSC)
並行GC(Parallel Old)/(Parallel MSC)
併發標記清除GC(CMS)
4個過程
-
初始標記(CMS initial mark)
-
併發標記(CMS concurrent mark)和用戶線程一起
-
重新標記(CMS remark)
-
併發清除(CMS concurrent sweep)和用戶線程一起
-
總體過程
優缺點
優點:
併發收集低停頓
缺點:
- 併發執行,對CPU資源壓力大
- 採用的標記清除算法會導致大量碎片
垃圾收集器配置代碼總結
底層代碼
G1垃圾收集器
以前收集器特點
- 年輕代和老年代是各自獨立且連續的內存塊
- 年輕代收集使用單eden+S0 +S進行復制算法
- 老年代收集必須掃描整個老年代區域
- 都是以儘可能少而快速地執行GC爲設計原則
G1是什麼
底層原理
Region區域化垃圾收集器
最大好處是化整爲零,避免全內存掃描,只需要按照區域來進行掃描即可
回收步驟
4步過程
常用配置參數(瞭解)
和CMS相比的優勢
總結
生產環境服務器變慢,診斷思路和性能評估
整機:top
uptime,系統性能命令的精簡版
CPU:vmstat
查看CPU(包含不限於)
查看額外
-
查看所有CPU核信息
mpstat -P ALL 2
-
每個進程使用cpu的用量分解信息
pidstat -u 1 -p 進程編號
內存:free
應用程序可用內存數
查看額外
pidstat -p 進程號 -r 採樣間隔秒數
硬盤:df
查看磁盤剩餘空閒數
磁盤IO:iostat
磁盤I/O性能評估
查看額外
pidstat -d 採樣間隔秒數 -p 進程號
網絡IO:ifstat
默認本地沒有,下載ifstat
查看網絡IO
假如生產環境出現CPU佔用過高,如何分析思路和定位
結合Linux和JDK命令一塊分析
案例步驟
-
先用top命令找出CPU佔比最高的
-
ps -ef或者jps進一步定位,得知是一個怎麼樣的一個後臺程序
-
定位到具體線程或者代碼
ps -mp 進程 -o THREAD,tid,time
-m 顯示所有線程
-p pid進程使用cpu的時間
-o 該參數後是用戶自定義格式
- 將需要的線程ID轉換爲16進制格式(英文小寫格式)
printf “%x\n” 有問題的線程ID
- jstack 進程ID | grep tid(16進制線程ID小寫英文) -A60
對於JDK自帶的JVM監控和性能分析工具用過哪些?一是怎麼用的?
性能監控工具
- jps(虛擬機進程狀況工具)
- jinfo(Java配置信息工具)
- jmap(內存映像工具)
- jstat(統計信息監控工具)