一、GC日誌分析html
爲了在內存溢出時排查緣由,能夠在JVM啓動時加一些參數來控制,當JVM內存出問題時能夠經過分析記錄下來的GC日誌,GC的頻率和每次GC回收了哪些內存。java
GC的日誌輸入有如下參數linux
1)-verbose:gc 能夠輔助輸出一些詳細的GC信息sql
2)-XX:+PrintGCDetails 輸出GC的詳細信息數組
3)-XX:+PrintGCApplicationStoppedTime 輸出GC形成應用程序暫停的時間瀏覽器
4)-XX:+PrintGCDateStamps 輸出GC發生的時間信息服務器
5)-XX:PrintHeapAtGC 在GC先後輸出堆中各個區域的大小eclipse
6)-Xloggc:[file] 將GC信息輸出到單獨的文件工具
每種GC方式輸出日誌的形式不一樣,除CMS的日誌和其餘GC方式差別較大外,其他GC方式的日誌能夠抽象成以下方式性能
[GC [<collector>: <starting occupancy1> -> <ending occupancy1> (total size1) , <pause time1> secs]
<starting occupancy2> -> <ending occupancy2> (total size2) , <pause time2> secs] ]
說明以下
1)<collectot>GC 表示垃圾收集器的名稱
2)<starting occupancy1> 表示Young區在GC前佔用的內存
3)<ending occupancy1> 表示Young區在GC後佔用的內存
4)(total size1) 表示Young區的總內存大小
5)<pause time1> 表示Young區局部收集時JVM暫停處理的時間 secs表示單位秒
6)<starting occupancy2> 表示Heap在GC前佔用的內存
7)<ending occupancy2> 表示Heap在GC後佔用的內存
8)(total size2) 表示Heap的總內存
9)<pause time2> 表示在GC過程當中JVM暫停處理的總時間
能夠根據日誌來判斷是否存在內存泄漏的問題:
<starting occupancy1> - <ending occupancy1> 和 <starting occupancy2> - <ending occupancy2> 比較
一、若是前者差等於後者差,代表Young區GC 對象100%被回收,沒有對象進入 Old區或者Perm區
二、若是前者大於後者,那麼差值就是此次GC對象進入Old或者Perm區的大小
若是隨着時間的的延長,<ending occupancy2>的大小一直在增加,並且Full GC很頻繁,那麼極可能就是內存泄漏致使的。
二、堆快照文件分析
如下Java命令在JDK的bin目錄下執行
經過命令 jmap -dump:format=b,file=[filename][pid] jmap(Memory Map for Java)
來記錄下堆的內存快照,而後利用第三方工具如eclipse 插件MAT來分析整個Heap的對象關聯狀況。
若是內存耗盡可直接致使JVM退出,能夠經過參數
-XX:+HeapDumpOnOutOfMemoryError 來配置當內存耗盡時記錄下當時的內存快照
-XX:HeapDumpPath 指定內存快照文件的路徑 文件快照的名稱格式爲 java_[pid].hprof
若是是OOM,可能有兩方面的緣由
一、內存分配太小,不知足程序運行所須要的內存
二、內存泄漏(FullGC頻繁,回收後Heap佔用的內存不斷增加)
三、JVM Crash 日誌分析
TODO
JVM性能監控和故障處理
經過工具導出和處理分析 運行日誌、異常堆棧、GC日誌、線程快照(threaddump/javacore文件)、堆轉儲快照(headdump/hprof文件)等
jps:JVM process status tool,顯示指定系統內全部的HotSpot虛擬機進程
jstat:JVM statistics Monitoring Tool,收集HotSpot虛擬機各方面的運行數據
jinfo:Configuration Info for java,顯示虛擬機配置信息
jmap:Memory map for Java,生成虛擬機的內存轉儲快照(heapdump文件)
jhat:JVM Heap Dump Browser,用於分析heapdump文件,它會創建一個http/html服務器,讓用戶能夠在瀏覽器上查看分析結果
jstack:Stack trace for Java,顯示虛擬機的線程快照
jps:(Jvm Process Status )和linux中ps命令類似,可列出正在運行的虛擬機進程,並顯示虛擬機執行主類和這些進程的惟一ID(Local Virtual Machine Identifier LVMID)
格式:jps [option] [hostid(主機名)]
參數:
-l 輸出主類的全路徑
-v 輸出虛擬機進程啓動是的JVM參數
jstat:用於監視虛擬機各類運行狀態信息的命令行工具,它能夠顯示本地或者遠程虛擬機進程中的類加載、內存、垃圾收集、JIT編譯等運行數據,是定位虛擬機性能問題的首選工具。
格式:jstat [ option vmid [interval] [count] ]
interval和count是查詢間隔和次數,若是忽略這兩個參數則只查詢一次
選項:
-class 監視類裝載、卸載數量、總空間以及類裝載消耗時間
-gc 監視Java堆情況,包含Eden區,兩個Survivor區、老年代、永久代等的容量,已用空間,GC時間等信息。
jmap:Java內存映射工具,用於生成堆存儲快照heapdump,生成堆快照還能夠經過設置參數使在OOM異常以後自動生成堆dump文件。
jmap還可查詢finalize執行隊列、Java堆和永久代的詳細信息(空間使用率,使用哪一種收集器等)。
格式:jmap [option] vmid
option參數
-dump:format=b,file=[filename] 生成堆轉儲快照
-heap 顯示Java堆詳細信息,如使用哪一種收集器、參數配置、分代情況等。
jhat:與jmap搭配使用,分析jmap生成的堆轉儲快照文件。通常不會直接使用jhat命令分析dump文件,一是不會直接在應用服務器上分析dump文件,由於分析耗時耗資源,二是jhat分析結果比較簡陋,可用VisualVM,MAT等工具
jstack:Java堆棧跟蹤工具,用戶生成虛擬機當前時刻的線程快照,線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成快照的主要目的是定位線程出現長時間等待的緣由,如線程間死鎖、死循環、請求外部資源(如sql)致使的長時間等待等。
線程出現停頓的時候經過jstack來查看各個線程的調用堆棧,就能夠知道沒有響應的線程到底在後臺作什麼事情或者等待什麼資源
格式:jstack [option] vmid
option參數:
-F:強制輸出線程堆棧
-l:除堆棧外顯示關於鎖的附加信息
-m:可顯示調用本地方法的堆棧
JDK1.5以後的Thread類新增了getAllStackTraces()方法用戶獲取虛擬機中全部線程的StackTraceElement對象。和jstack功能相似
public static Map<Thread,StackTraceElement[]> getAllStackTraces() 返回從 Thread 到 StackTraceElement 數組的一個 Map,表明相應線程的堆棧跟蹤。 、
總結:
若是要定位OOM問題使用jps和jmap組合命令,先用jps或者linux的ps命令查看虛擬機進程的vmid,而後用jamp命令生成堆快照文件,最後使用工具分析dump文件定位問題。
若是要定位線程響應時間過長的問題,使用jps和jstack命令,先用jps或者linux的ps命令查看虛擬機進程的vmid,而後用jstack命令查看線程堆棧信息
JVM調優
JVM調優是經過分析GC日誌等來分析java內存和垃圾回收的狀況,來調整各內存區域內存佔比和垃圾回收策略。
GC優化的根本緣由
垃圾收集器的工做就是清除Java建立的對象,垃圾收集器須要清理的對象數量以及要執行的GC數量均取決於已建立的對象數量。所以,爲了使你的系統在GC上表現良好,首先須要在保證功能的基礎上減小建立對象的數量。
如:養成以下的良好的編碼習慣
一、使用StringBuffer或StringBuilder來代替String
二、儘可能少輸出日誌
GC優化的兩個目的
一、減小Full GC的頻率
二、減小Full GC的執行時間
一、減小Full GC的頻率——將進入老年代的對象數量降到最低
充分使用系統資源,減小GC停頓時間和停頓次數,因爲Full GC的停頓時間遠比Minor GC的停頓時間長,所以要控制Full GC的頻率。
控制Full GC的頻率的關鍵是將進入老年代的對象數量降到最低。所以要看應用中的絕大多數對象是否符合「朝生夕滅」的原則,即大多數的對象的生存時間都不該太長,尤爲是不能有成批量的、長時間存活的對象產生,這樣這些對象在Minor GC就會被回收,不會進入老年代,這樣才能保證老年代的穩定。
好比對於十幾小時乃至一天才出現一次Full GC的系統能夠經過定時任務的方式在夜間觸發Full GC。
若是FullGC次數過多多是下面的緣由:
一、內存佔用高:代碼中建立了大量的對象致使內存泄漏,不能回收內存,建立新對象致使空間不足觸發fullGC
二、內存佔用不高:多是顯示的調用System.gc()次數太多致使的fullGC,能夠經過添加-XX:+DisableExplicitGC來禁用JVM對顯式GC的響應
二、減小Full GC的時間
Full GC的停頓時間遠比Minor GC的停頓時間長,所以,若是在Full GC上花費過多的時間(超過1s), 將可能出現超時錯誤。
1)若是經過減少老年代內存來減小Full GC時間,可能會引發OutOfMemoryError或者致使Full GC的頻率升高。
2)若是經過增長老年代內存來下降Full GC的頻率,Full GC的時間可能所以增長。
所以,你須要把老年代的大小設置成一個「合適」的值。
影響GC性能的因素:
1)-XX:NewRatio 新生代和老年代的內存比(默認1:2),這個參數將對GC性能產生重要的影響
2)垃圾收集器的類型
何時須要進行GC優化? 經過監控GC狀態,而後分析GC監控結果來判斷是否須要進行GC優化。 若是GC執行時間知足下列全部條件,就沒有必要進行GC優化了: 1)Minor GC執行很是迅速(50ms之內) 2)Minor GC沒有頻繁執行(大約10s執行一次) 3)Full GC執行很是迅速(1s之內) 4)Full GC沒有頻繁執行(大約10min執行一次) GC優化是一個不斷嘗試並逐漸調試的過程。在每次設置完GC參數後,要收集數據,並收集至少24個小時以後再進行結果分析。