1. 程式人生 > >通過Java/JMX得到full GC次數

通過Java/JMX得到full GC次數

今天有個同事問如何能通過JMX獲取到某個Java程序的full GC次數: 
引用 hi,問個問題,怎們在java中獲取到full gc的次數呢? 
我現在用jmx的那個得到了gc次數,不過不能細化出來full gc的次數 

Java程式碼  收藏程式碼
  1. for (final GarbageCollectorMXBean garbageCollector  
  2.         : ManagementFactory.getGarbageCollectorMXBeans()) {  
  3.     gcCounts += garbageCollector.getCollectionCount();  
  4. }  

你比如我現在是這樣拿次數的
我回答說因為full GC概念只有在分代式GC的上下文中才存在,而JVM並不強制要求GC使用分代式實現,所以JMX提供的標準MXBean API裡不提供“full GC次數”這樣的方法也正常。 
既然“full GC”本來就是非常平臺相關的概念,那就hack一點,用平臺相關的程式碼來解決問題好了。這些GC的MXBean都是有名字的,而主流的JVM的GC名字相對穩定,非要通過JMX得到full GC次數的話,用名字來判斷一下就好了。 

舉個例子來看看。通過JDK 6自帶的JConsole工具來檢視相關的MXBean的話,可以看到, 

GC的MXBean在這個位置: 


這個例子是用server模式啟動JConsole的,使用的是ParallelScavenge GC,它的年老代對應的收集器在這裡: 



該收集器的總收集次數在此,這也就是full GC的次數: 


於是只要知道我們用的JVM提供的GC MXBean的名字與分代的關係,就可以知道full GC的次數了。 
Java程式碼寫起來冗長,這帖就不用Java來寫例子了,反正API是一樣的,意思能表達清楚就OK。 
用一個Groovy指令碼簡單演示一下適用於Oracle (Sun) HotSpot與Oracle (BEA) JRockit的GC統計程式: 
Groovy程式碼  收藏程式碼
  1. import java.lang.management.ManagementFactory  
  2. printGCStats = {  
  3.   def youngGenCollectorNames = [  
  4.     // Oracle (Sun) HotSpot  
  5.     // -XX:+UseSerialGC  
  6.     'Copy',  
  7.     // -XX:+UseParNewGC  
  8.     'ParNew',  
  9.     // -XX:+UseParallelGC  
  10.     'PS Scavenge',  
  11.     // Oracle (BEA) JRockit  
  12.     // -XgcPrio:pausetime  
  13.     'Garbage collection optimized for short pausetimes Young Collector',  
  14.     // -XgcPrio:throughput  
  15.     'Garbage collection optimized for throughput Young Collector',  
  16.     // -XgcPrio:deterministic  
  17.     'Garbage collection optimized for deterministic pausetimes Young Collector'  
  18.   ]  
  19.   def oldGenCollectorNames = [  
  20.     // Oracle (Sun) HotSpot  
  21.     // -XX:+UseSerialGC  
  22.     'MarkSweepCompact',  
  23.     // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting)  
  24.     'PS MarkSweep',  
  25.     // -XX:+UseConcMarkSweepGC  
  26.     'ConcurrentMarkSweep',  
  27.     // Oracle (BEA) JRockit  
  28.     // -XgcPrio:pausetime  
  29.     'Garbage collection optimized for short pausetimes Old Collector',  
  30.     // -XgcPrio:throughput  
  31.     'Garbage collection optimized for throughput Old Collector',  
  32.     // -XgcPrio:deterministic  
  33.     'Garbage collection optimized for deterministic pausetimes Old Collector'  
  34.   ]  
  35.   R: {  
  36.     ManagementFactory.garbageCollectorMXBeans.each {  
  37.       def name  = it.name  
  38.       def count = it.collectionCount  
  39.       def gcType;  
  40.       switch (name) {  
  41.       case youngGenCollectorNames:  
  42.         gcType = 'Minor Collection'  
  43.         break  
  44.       case oldGenCollectorNames:  
  45.         gcType = 'Major Collection'  
  46.         break  
  47.       default:  
  48.         gcType = 'Unknown Collection Type'  
  49.         break  
  50.       }  
  51.       println "$count <- $gcType: $name"  
  52.     }  
  53.   }  
  54. }  
  55. printGCStats()  

執行可以看到類似這樣的輸出: 
Command prompt程式碼  收藏程式碼
  1. 5 <- Minor Collection: Copy  
  2. 0 <- Major Collection: MarkSweepCompact  

↑這是用client模式的HotSpot執行得到的; 
Command prompt程式碼  收藏程式碼
  1. 0 <- Minor Collection: Garbage collection optimized for throughput Young Collector  
  2. 0 <- Major Collection: Garbage collection optimized for throughput Old Collector  

↑這是用JRockit R28在32位Windows上的預設模式得到的。 

通過上述方法,要包裝起來方便以後使用的話也很簡單,例如下面Groovy程式: 
Groovy程式碼  收藏程式碼
  1. import java.lang.management.ManagementFactory  
  2. class GCStats {  
  3.   static final List<String> YoungGenCollectorNames = [  
  4.     // Oracle (Sun) HotSpot  
  5.     // -XX:+UseSerialGC  
  6.     'Copy',  
  7.     // -XX:+UseParNewGC  
  8.     'ParNew',  
  9.     // -XX:+UseParallelGC  
  10.     'PS Scavenge',  
  11.     // Oracle (BEA) JRockit  
  12.     // -XgcPrio:pausetime  
  13.     'Garbage collection optimized for short pausetimes Young Collector',  
  14.     // -XgcPrio:throughput  
  15.     'Garbage collection optimized for throughput Young Collector',  
  16.     // -XgcPrio:deterministic  
  17.     'Garbage collection optimized for deterministic pausetimes Young Collector'  
  18.   ]  
  19.   static final List<String> OldGenCollectorNames = [  
  20.     // Oracle (Sun) HotSpot  
  21.     // -XX:+UseSerialGC  
  22.     'MarkSweepCompact',  
  23.     // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting)  
  24.     'PS MarkSweep',  
  25.     // -XX:+UseConcMarkSweepGC  
  26.     'ConcurrentMarkSweep',  
  27.     // Oracle (BEA) JRockit  
  28.     // -XgcPrio:pausetime  
  29.     'Garbage collection optimized for short pausetimes Old Collector',  
  30.     // -XgcPrio:throughput  
  31.     'Garbage collection optimized for throughput Old Collector',  
  32.     // -XgcPrio:deterministic  
  33.     'Garbage collection optimized for deterministic pausetimes Old Collector'  
  34.   ]  
  35.   static int getYoungGCCount() {  
  36.     ManagementFactory.garbageCollectorMXBeans.inject(0) { youngGCCount, gc ->  
  37.       if (YoungGenCollectorNames.contains(gc.name))  
  38.         youngGCCount + gc.collectionCount  
  39.       else  
  40.         youngGCCount  
  41.     }  
  42.   }  
  43.   static int getFullGCCount() {  
  44.     ManagementFactory.garbageCollectorMXBeans.inject(0) { fullGCCount, gc ->  
  45.       if (OldGenCollectorNames.contains(gc.name))  
  46.         fullGCCount + gc.collectionCount  
  47.       else  
  48.         fullGCCount  
  49.     }  
  50.   }  
  51. }  

用的時候: 
Groovysh程式碼  收藏程式碼
  1. D:\>\sdk\groovy-1.7.2\bin\groovysh  
  2. Groovy Shell (1.7.2, JVM: 1.6.0_20)  
  3. Type 'help' or '\h' for help.  
  4. --------------------------------------------------  
  5. groovy:000> GCStats.fullGCCount  
  6. ===> 0  
  7. groovy:000> System.gc()  
  8. ===> null  
  9. groovy:000> GCStats.fullGCCount  
  10. ===> 1  
  11. groovy:000> System.gc()  
  12. ===> null  
  13. groovy:000> System.gc()  
  14. ===> null  
  15. groovy:000> GCStats.fullGCCount  
  16. ===> 3  
  17. groovy:000> GCStats.youngGCCount  
  18. ===> 9  
  19. groovy:000> GCStats.youngGCCount  
  20. ===> 9  
  21. groovy:000> GCStats.youngGCCount  
  22. ===> 9  
  23. groovy:000> System.gc()  
  24. ===> null  
  25. groovy:000> GCStats.youngGCCount  
  26. ===> 9  
  27. groovy:000> GCStats.fullGCCount  
  28. ===> 4  
  29. groovy:000> quit  

這是在Sun JDK 6 update 20上跑的。順帶一提,如果這是跑在JRockit上的話,那full GC的次數就不會增加——因為JRockit裡System.gc()預設是觸發young GC的;請不要因為Sun HotSpot的預設行為而認為System.gc()總是會觸發full GC的。 

Poonam Bajaj以前也寫過一篇blog提到HotSpot VM裡的GC MBean的名字的: 
Collector names for GarbageCollectorMXBean MXBean

關於JMX的MXBean的使用,也可以參考下面兩篇文件: 
Groovy and JMX
Monitoring the JVM Heap with JRuby

相關推薦

通過Java/JMX得到full GC次數

今天有個同事問如何能通過JMX獲取到某個Java程序的full GC次數:  引用 hi,問個問題,怎們在java中獲取到full gc的次數呢?  我現在用jmx的那個得到了gc次數,不過不能細化出來full gc的次數  Java程式碼   for (fina

系統執行緩慢,CPU 100%,以及Full GC次數過多問題的排查思路及解決方案

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

系統運行緩慢,CPU 100%,以及Full GC次數過多問題的排查思路

底部 力度 users nts java程序 來源 $$ 不定 進程 前言 處理過線上問題的同學基本上都會遇到系統突然運行緩慢,CPU 100%,以及Full GC次數過多的問題。當然,這些問題的最終導致的直觀現象就是系統運行緩慢,並且有大量的報警。 本文主要針對系統運行緩

Java獲取full GC次數

大家如果熟悉JDK 6的內建工具,或許已經知道可以通過jstat工具很輕鬆的從外部得知一個Java程序的GC統計資訊,其中就包括了full GC的次數。 假定我們相信jstat的資料是準確的,那麼只要跟它從同一來源獲取資料就可以保證我們拿到正確的full GC次數資訊了。

Java虛擬機器7:記憶體溢位和記憶體洩露、並行和併發、Minor GCFull GC、Client模式和Server模式的區別

記憶體溢位和記憶體洩露的區別 1、記憶體溢位 記憶體溢位指的是程式在申請記憶體的時候,沒有足夠大的空間可以分配了。 2、記憶體洩露 記憶體洩露指的是程式在申請記憶體之後,沒有辦法釋放掉已經申請到記憶體,它始終佔用著記憶體,即被分配的物件可達但無用。記憶體洩露一般都是因

JAVA 10原始碼閱讀筆記之JEP-307(G1的並行Full GC

# 1. 背景 JEP-307解決了G1垃圾回收器的一個嚴重的問題,截止到Java 9,G1的Full GC採用的是單執行緒演算法,嚴重影響效能,無法利用到多核能力進行垃圾回收。JEP-307修復了此問題,發生Full GC時允許使用多個執行緒進行並行回收。 # 2. G1

java-jvm-full gc頻繁的分析及解決

關於應用full gc頻繁的分析及解決 很久前的工作日記了,移到ITeye上來。 現象 系統報警full gc次數過多,每2分鐘達到了5~6次,這是不正常的現象 在full gc報警時的gc.log如下: 在full gc報警時的jstat如下: sudo -u admin -H /opt/taobao/

java在什麼情況下觸發Full GC

1. 舊生代空間不足 舊生代空間只有在新生代物件轉入及建立為大物件、大陣列時才會出現不足的現象,當執行Full GC後空間仍然不足,則丟擲如下錯誤: java.lang.OutOfMemoryError: Java heap space 為避免以上兩種狀況引起的Full

java nio多執行緒引起的full gc問題

1.在寫nio的例子時,服務端採用執行緒池處理請求,遇到一個full gc問題,下面給程式碼貼出來。 nioserver端程式碼 package com.nio.study; import java.io.IOException; import jav

簡述Java記憶體分配和回收策略以及Minor GC 和 Major GC(Full GC)

記憶體分配: 1. 棧區:棧可分為Java虛擬機器和本地方法棧 2. 堆區:堆被所有執行緒共享,在虛擬機器啟動時建立,是唯一的

Spring裝配bean--02通過Java代碼裝配bean

三方 應用 context his 單獨 stc ring -- oid Spring容器負責創建應用程序中的bean並通過DI來協調這些對象之間的關系 Spring提供了三種主要的裝配機制: 在XML中進行顯式配置 在Java中進行顯式配置 隱式

(轉)通過Java SE 7自帶的監控服務(WatchService API)實現類似.NET FileWatcher的功能

thread new and mar chan col att 項目 chang 轉自:http://www.cnblogs.com/callwangxiang/archive/2011/08/04/JavaDirectoryWatcherFileWatcher.html

巴菲特公式:如何通過閱讀變更聰明

ucc 答案 建議 電腦 努力 每天 是我 思想 ner 巴菲特公式:如何通過閱讀變得更聰明   當今世界最傳奇的投資家巴菲特,從來沒有停止過閱讀。閱讀讓他發現潛在投資目標,閱讀讓他減少出錯。          “一個人能做到的最好的事情就是幫助另一個人了解更

Full GC

onf 5.0 並發 net 滿了 執行c 發的 cms gc 反射 1,新生代:(1)所有對象創建在新生代的Eden區,當Eden區滿後觸發新生代的Minor GC,將Eden區和非空閑Survivor區存活的對象復制到另外一個空閑的Survivor區中。(2)保證一個S

Java垃圾回收(GC)機制詳解

nbsp 引用計數 維護 png 對象 最新 新的 com 前沿 垃圾回收算法有兩種,根據不同的虛擬機策略不同 1、引用計數法 2、可達性分析法 由於我們平常使用的hotspot虛擬機用的是第二種。 那哪些是可達的呢? 這個算法的基本思想是通過一系列稱為“GC Roots”

full GC觸發的條件

錯誤 failure tab 大於 lur vivo abort mar 進行 full GC觸發的條件除直接調用System.gc外,觸發Full GC執行的情況有如下四種。1. 舊生代空間不足舊生代空間只有在新生代對象轉入及創建為大對象、大數組時才會出現不足的現象,當執

通過Java獲取圖片的信息

edi 取圖 out print ring str public ioe ack 1. 圖片:96 * 96 2. 程序如下: package com.bnc.bufferedImage; import java.awt.Image; import java.

java通過java.net.URL發送http請求調用接口

urn color val return http 功能 enc nts 實例 一般在*.html,*.jsp頁面中我們通過使用ajax調用接口,這個是我們通常用的。對於這些接口,大都是本公司寫的接口供自己調用,所以直接用ajax就可以。但是,如果是多家公司共同開發一個東西

spring boot框架學習學前掌握之重要註解(2)-通過java的配置方式進行配置spring

凱哥java kaigejava本節主要內容:1:通過代碼演示實現零XML配置spring2:使用重點註解理解聲明:本文是《凱哥陪你學系列-框架學習之spring boot框架學習》中spring boot框架學習學前掌握之重要註解(2)-通過java的配置方式進行配置spring.在上一節《spring b

通過Java對象來遍歷成員方法,成員變量,構造函數

return pri typename static spa tde log 繼承 red 1 package classTest; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.ref