寫在前面:
該系列文章,主要是為了深入學習Java完成的一條鏈,推薦閱讀的整體順序為:Java的內存模型(根源),一個java文件被執行的歷程,一個Java類的加載,Java的垃圾回收機制及算法,Linux(六):系統運維常用命令 和 Java程序運行狀態的監控(實用,定位Java程序問題)
JVM的內存模型
在進行GC的時候,不考慮方法區和棧區的部分,因為在java中,垃圾回收主要是針對對象,也就是堆區內存,如上圖,堆內存在實際中是分層的;實質上是分為三大塊,即新生代(YoungGen)、老年代(Old Memory)、永久區(Perm),新生代又細分為伊甸區(Eden)、生還區(S0、S1),其中伊甸區主要是存放剛誕生的對象(即代碼中新new出的對象),S1,S2主要存放新生代經過垃圾清理后存活的對象;
注:這里用的是老圖,永久區(Perm)在Java8已經被取締了
垃圾回收的過程
垃圾回收即GC,主要分為兩種,一種為Minor GC,也叫YGC,是最頻繁的GC,發生在新生代,Java應用在運行過程中會大量的創建對象,這些對象可能用完即銷毀,所以基本在新生代就被回收了。另一種稱為Major GC,主要發生在老年代;還有一個含糊不定的概念,即FullGC,大眾理解的話,當老年代也滿了,則會對整個堆內存進行全量的回收。但是實際情況中,我們主要看的是gc.log日志,其中也會發現在部分gc日志頭中也有Full GC字眼,此處表示含義是在這次GC的全過程中,都是STW的狀態,也就是說在這次GC的全過程中所有用戶線程都是處於暫停的狀態。
STW狀態:
stop the world指的是用戶線程在運行至安全點(safe point)或安全區域(safe region)之后,就自行掛起,進入暫停狀態,對外的表現看起來就像是全世界都停止運轉了一樣,而不論何種gc算法,不論是minor gc還是major gc都會stop the world,區別只在於stop the world的時間長短。
當發生YGC,新生代中沒有被任何其他對象所引用的對象將會從內存中被清除,還被其他對象引用的則放到幸存者區。當發生多次YGC,在S0、S1區多次沒有被清楚的對象,則會被移到老年代區域。當老年代區域被占滿的時候,則會發送Major GC。
監控命令
jps命令:虛擬機進程狀況
查看所有的jvm進程,包括進程ID,進程啟動的路徑等等。
命令格式:
jps [option]
參數選項:
選項 | 作用 |
-q | 只輸出LVMID,省略主類的名稱 |
-m | 輸出虛擬機進程啟動時傳遞給主類main()函數的參數 |
-l | 輸出主類的全名,如果進程執行的是jar包,則輸出jar路徑 |
-v | 輸出虛擬機進程啟動時的JVM參數 |

jstat命令:虛擬機統計信息監視工具
jstat(JVM Statistics Monitoring Tool)是用於監視虛擬機各種運行狀態信息的命令行工具。它可以顯示本地或者遠程[1]虛擬機進程中的類加載、內存、垃圾收集、即時編譯等運行時數據,在沒有GUI圖形界面、只提供了純文本控制台環境的服務器上,它將是運行期定位虛擬機性能問題的常用工具。
命令格式:
jstat [ option vmid [interval[s|ms] [count]] ]
參數option為命令選項,vmid則是通過jps獲取到的jvm運行號,參數interval和count代表查詢間隔和次數,如果省略這2個參數,說明只查詢一次。如果每秒進行10次監聽,則命令為 jstat -XX vmid 1000 10
參數選項:
參數 | 作用 |
-class | 監視類加載、卸載數量,總空間以及類裝載所耗費的時間 |
-gc | 監視java堆狀況,包括Eden區、2個survival區、老年代,永久代等的容量,已用空間,垃圾收集時間合計等信息。 |
-gccapacity | 監視內容與-gc基本相同,但輸出主要關注java堆各個區域所用到的最大、最小空間。 |
-gcutil | 監視內容與-gc基本相同,單輸出主要關注已用空間占總空間的百分比。 |
-gccause | 與-gcutil功能一樣,但是會額外輸出導致上一次垃圾收集產生的原因。 |
-gcnew | 監視新生代垃圾收集狀況 |
-gcnewcapacity | 監視內容與-gcnew基本相同,輸出主要關注使用到的最大、最小空間。 |
-gcold | 監視老年代垃圾收集狀況。 |
-gcoldcapacity | 監視內容與-gcold基本線頭,輸出主要關注使用的最大、最小空間。 |
-gcpermcapacity | 輸出永久代用到的最大、最小空間。 |
-compiler | 輸出即時編譯器編譯過的方法、耗時等信息。 |
-printtcompilation | 輸出已經被即時編譯的方法。 |
以上實際使用過程中,並不會全部用到,較為常用的主要為-class、-gc、-gcutil;
執行樣例:
-class
返回解釋:
#Loaded 類加載數量
#Bytes 加載的大小(k)
#Unloaded 類卸載的數量
#Bytes 卸載的大小(k)
#Time 時間花費在執行類加載和卸載操作
-gc
-gcutil
返回解釋:
#S0C 生還者區0 容量(KB)
#S1C 生還者區1 容量(KB)
#S0U 生還者區0 使用量(KB)
#S1U 生還者區1 使用量(KB)
#EC 伊甸園區容量(KB)
#EU 伊甸園區使用量(KB)
#OC 老年區容量(KB)
#OU 老年區使用量(KB)
#PC 永久區容量(KB)
#PU 永久區使用量(KB)
#YGC 新生代GC次數
#YGCT 新生代GC時間
#FGC full GC 事件的次數
#FGCT full GC的時間
#GCT 總GC時間
jinfo:Java配置信息工具
jinfo(Configuration Info for Java)的作用是實時查看和調整虛擬機各項參數。使用jps命令的-v參數可以查看虛擬機啟動時顯式指定的參數列表。
jstack:Java堆棧跟蹤工具
jstack(Stack Trace for Java)命令用於生成虛擬機當前時刻的線程快照(一般稱為threaddump或者javacore文件)。線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的目的通常是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間掛起等,都是導致線程長時間停頓的常見原因。線程出現停頓時通過jstack來查看各個線程的調用堆棧,就可以獲知沒有響應的線程到底在后台做些什么事情,或者等待着什么資源。
命令格式:
jstack [ option ] vmid
參數選項:
參數 | 作用 |
-L | 除堆棧外,顯示關於鎖的附加信息。 |
-F | 當正常輸出的請求不被響應時,強制輸出線程堆棧 |
執行樣例: