沒有被其餘對象引用java
(1)引用計數法git
優勢and缺點github
(2)可達性分析算法算法
根節點:類加載器、Thread、虛擬機棧的本地變量表、static 成員、常量引用、本地方法棧的變量
缺點是內存空間碎片化太嚴重安全
(1)複製算法介紹服務器
(2)複製算法優點多線程
(1)標記整理算法介紹併發
(2)標記整理算法優勢oracle
年輕代用的是複製算法
老年代 用的是標記清除或者標記整理算法
(2)年輕代內存空間maven
若是Eden區不能保存一個較大的對象,則會保存到老年代中,默認十五歲以後會轉移到老年代中
-XX:PretenureSizeThreshold 對象分配:對象優先在 Eden 區分配、大對象直接進入Old 區
-XX:MaxTenuringThreshold 長期存活對象進入 Old 區
-XX:+PrintTenuringDistribution若是但願跟蹤每次新生代GC後,survivor區中對象的年齡分佈,可在啓動參數上增長。
-XX:TargetSurvivorRatio
設定survivor區的目標使用率。默認50,即survivor區對象目標使用率爲50%。
爲何要動態的計算tenuring threshold的值呢?假設有不少年齡還未達到TenuringThreshold的對象依舊停留在survivor區,這樣不利於新對象從eden晉升到survivor。所以設置survivor區的目標使用率,當使用率達到時從新調整TenuringThreshold值,讓對象儘早的去old區。
(1)GC分類
從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱爲 Minor GC
Full GC 是清理整個堆空間—包括年輕代和老年代。
Major GC 是清理老年代
JVM中的堆,通常分爲三大部分:新生代、老年代、永久代:
永久代
指內存的永久保存區域,主要存放Class和Meta(元數據)的信息,Class在被加載的時候被放入永久區域. 它和和存放實例的區域不一樣,GC不會在主程序運行期對永久區域進行清理。因此這也致使了永久代的區域會隨着加載的Class的增多而脹滿,最終拋出OOM異常。
在Java8中,永久代已經被移除,被一個稱爲「元數據區」(元空間)的區域所取代。
(3)對象如何晉升到老年代
(4)設置參數
(5)觸發full GC的方法
JVM有兩種運行模式Server與Client。兩種模式的區別在於,Client模式啓動速度較快,Server模式啓動較慢;可是啓動進入穩按期長期運行以後Server模式的程序運行速度比Client要快不少。這是由於Server模式啓動的JVM採用的是重量級的虛擬機,對程序採用了更多的優化;而Client模式啓動的JVM採用的是輕量級的虛擬機。因此Server啓動慢,但穩定後速度比Client遠遠要快。
使用Java -version命令就能顯示出當前虛擬機處於哪一種模式。
Client:
以下圖所示,能夠看到HotSpot虛擬機採用Client模式啓動的。
串行收集器
單線程收集器
Serial::Serial, Serial Old
並行收集器
吞吐量優先 是說垃圾收集線程之間並行工做 用戶線程處在等待狀態 適合交互性比較弱的場景
吞吐量:花在垃圾收集的時間和花在應用時間的佔比 -XX:GCTimeRatio=<n>,垃圾收集時間佔1/(1+n)
Parallel(吞吐量優先, Server 模式默認收集器):Parallel Scavenge, Parallel Old
併發收集器
併發收集器 停頓時間優先 垃圾收集線程和用戶線程一塊兒執行 適合對相應時間有要求的場景
停頓時間:垃圾收集器作垃圾回收中斷應用執行的時間 -XX:MaxGCPauseMillis
Concurent(停頓時間優先):CMS , G1
如何選擇垃圾收集器?
1. 優先調整堆的大小讓服務器本身來選擇
2. 若是內存小於100M,使用串行收集器
3。 若是是單核,而且沒有停頓時間的要求,選擇串行或者 JVM 本身選
4. 若是容許停頓時間超過1秒,選擇並行或 JVM 本身選
5. 若是響應時間最重要,而且不能超過1秒,使用併發收集器
3.Parallel Scavenge收集器(複製算法-多線程-Server模式下)
G1的幾個概念
Region
SATB:Snapshot-At-The-Beginning,它是經過 Root Tracing 獲得的,GC 開始時候存活對象的快照。
RSet:記錄了其餘 Region中的對象引用本 Region 中對象的關係,屬於 points-into 結構
YoungGC
新對象進入 Eden 區
存活對象拷貝到Survivor 區
存活時間達到年齡閾值時,對象晉升到 Old 區
MixedGC
不是 FullGC,回收全部的 Young和全部的 Old
global concurrent marking
1. Initial marking phase: 標記 GC Root, STW
2. Root region scanning phase:標記存活 Region
3. Concurrent marking phase:標記存活的對象
4. Remark phase:從新標記,STW
5. Cleanup phase:部分 STW
MixedGC時機
InitiatingHeapOccupancyPercent
G1HeapWastePercent
G1MixedGCLiveThresholdPercent
G1MixedGCCountTarget
G1OldGCSetRegionThresholdPercent
-XX:+UseG1GC 開啓 G1
-XX:G1HeapRegionSize=n, Region 的大小,1-32M,最多2048個
-XX:MaxGCPauseMillis=200 最大停頓時間
-XX:G1NewSizePercent、-XX:G1MaxNewSizePercent
-XX:G1ReservePercent=10 保留防止 to space溢出
-XX:ParallelGCThreads=n SWT線程數
-XX:ConcGCThreads=n 併發線程數=1/4*並行
最佳實踐
年輕代大小:避免使用-Xmn, -XX:NewRatio 等顯式 Young 區大小,會覆蓋暫停時間目標
暫停時間目標:暫停時間不要太嚴苛,其吞吐量目標是90%的應用程序時間和10%的垃圾回收時間,太嚴苛會直接影響到吞吐量
須要切換到 G1的狀況:
1. 50%以上的堆被存活對象佔用
2. 對象分配和晉升的速度變化很是大
3. 垃圾回收時間特別長,超過了1秒
可視化 GC 日誌分析工具
打印日誌相關參數:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution
例(默認爲 ParallelGC, 其它的添加-XX:+UseConcMarkSweepGC或-XX:+UseG1GC便可):
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log"
在線工具:http://gceasy.io/
訪問 GCeasy 官網導入日誌便可獲取可視化分析及優先建議
mvn clean package -Dmaven.test.skip 生成 jar包,雙擊執行,導入日誌便可進入圖形化分析頁面