通过Java

Posted on

通过Java/JMX得到full GC次数? - 高级语言虚拟机

您还未登录 ! 登录 注册

ITeye3.0

群组首页编程语言高级语言虚拟机知识库JVM实战通过Java/JMX得到full GC次数? 原创作者: RednaxelaFX 阅读:2261次 评论:1条 更新时间:2011-05-26

今天有个同事问如何能通过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. }
    for (final GarbageCollectorMXBean garbageCollector : ManagementFactory.getGarbageCollectorMXBeans()) { gcCounts += garbageCollector.getCollectionCount(); } 你比如我现在是这样拿次数的 我回答说因为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代码 收藏代码

  5. import java.lang.management.ManagementFactory

  6. printGCStats = {
  7. def youngGenCollectorNames = [
  8. // Oracle (Sun) HotSpot
  9. // -XX:+UseSerialGC
  10. 'Copy',
  11. // -XX:+UseParNewGC
  12. 'ParNew',
  13. // -XX:+UseParallelGC
  14. 'PS Scavenge',
  15. // Oracle (BEA) JRockit
  16. // -XgcPrio:pausetime
  17. 'Garbage collection optimized for short pausetimes Young Collector',
  18. // -XgcPrio:throughput
  19. 'Garbage collection optimized for throughput Young Collector',
  20. // -XgcPrio:deterministic
  21. 'Garbage collection optimized for deterministic pausetimes Young Collector'
  22. ]
  23. def oldGenCollectorNames = [
  24. // Oracle (Sun) HotSpot
  25. // -XX:+UseSerialGC
  26. 'MarkSweepCompact',
  27. // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting)
  28. 'PS MarkSweep',
  29. // -XX:+UseConcMarkSweepGC
  30. 'ConcurrentMarkSweep',
  31. // Oracle (BEA) JRockit
  32. // -XgcPrio:pausetime
  33. 'Garbage collection optimized for short pausetimes Old Collector',
  34. // -XgcPrio:throughput
  35. 'Garbage collection optimized for throughput Old Collector',
  36. // -XgcPrio:deterministic
  37. 'Garbage collection optimized for deterministic pausetimes Old Collector'
  38. ]
  39. R: {
  40. ManagementFactory.garbageCollectorMXBeans.each {
  41. def name = it.name
  42. def count = it.collectionCount
  43. def gcType;
  44. switch (name) {
  45. case youngGenCollectorNames:
  46. gcType = 'Minor Collection'
  47. break
  48. case oldGenCollectorNames:
  49. gcType = 'Major Collection'
  50. break
  51. default:
  52. gcType = 'Unknown Collection Type'
  53. break
  54. }
  55. println "$count <- $gcType: $name"
  56. }
  57. }
  58. }
  59. printGCStats()
    import java.lang.management.ManagementFactory printGCStats = { def youngGenCollectorNames = [ // Oracle (Sun) HotSpot // -XX:+UseSerialGC 'Copy', // -XX:+UseParNewGC 'ParNew', // -XX:+UseParallelGC 'PS Scavenge', // Oracle (BEA) JRockit // -XgcPrio:pausetime 'Garbage collection optimized for short pausetimes Young Collector', // -XgcPrio:throughput 'Garbage collection optimized for throughput Young Collector', // -XgcPrio:deterministic 'Garbage collection optimized for deterministic pausetimes Young Collector' ] def oldGenCollectorNames = [ // Oracle (Sun) HotSpot // -XX:+UseSerialGC 'MarkSweepCompact', // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting) 'PS MarkSweep', // -XX:+UseConcMarkSweepGC 'ConcurrentMarkSweep', // Oracle (BEA) JRockit // -XgcPrio:pausetime 'Garbage collection optimized for short pausetimes Old Collector', // -XgcPrio:throughput 'Garbage collection optimized for throughput Old Collector', // -XgcPrio:deterministic 'Garbage collection optimized for deterministic pausetimes Old Collector' ] R: { ManagementFactory.garbageCollectorMXBeans.each { def name = it.name def count = it.collectionCount def gcType; switch (name) { case youngGenCollectorNames: gcType = 'Minor Collection' break case oldGenCollectorNames: gcType = 'Major Collection' break default: gcType = 'Unknown Collection Type' break } println "$count <- $gcType: $name" } } } printGCStats() 执行可以看到类似这样的输出: Command prompt代码 收藏代码

  60. 5 <- Minor Collection: Copy

  61. 0 <- Major Collection: MarkSweepCompact
    5 <- Minor Collection: Copy 0 <- Major Collection: MarkSweepCompact ↑这是用client模式的HotSpot执行得到的; Command prompt代码 收藏代码

  62. 0 <- Minor Collection: Garbage collection optimized for throughput Young Collector

  63. 0 <- Major Collection: Garbage collection optimized for throughput Old Collector
    0 <- Minor Collection: Garbage collection optimized for throughput Young Collector 0 <- Major Collection: Garbage collection optimized for throughput Old Collector ↑这是用JRockit R28在32位Windows上的默认模式得到的。 通过上述方法,要包装起来方便以后使用的话也很简单,例如下面Groovy程序: Groovy代码 收藏代码

  64. import java.lang.management.ManagementFactory

  65. class GCStats {
  66. static final List YoungGenCollectorNames = [
  67. // Oracle (Sun) HotSpot
  68. // -XX:+UseSerialGC
  69. 'Copy',
  70. // -XX:+UseParNewGC
  71. 'ParNew',
  72. // -XX:+UseParallelGC
  73. 'PS Scavenge',
  74. // Oracle (BEA) JRockit
  75. // -XgcPrio:pausetime
  76. 'Garbage collection optimized for short pausetimes Young Collector',
  77. // -XgcPrio:throughput
  78. 'Garbage collection optimized for throughput Young Collector',
  79. // -XgcPrio:deterministic
  80. 'Garbage collection optimized for deterministic pausetimes Young Collector'
  81. ]
  82. static final List OldGenCollectorNames = [
  83. // Oracle (Sun) HotSpot
  84. // -XX:+UseSerialGC
  85. 'MarkSweepCompact',
  86. // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting)
  87. 'PS MarkSweep',
  88. // -XX:+UseConcMarkSweepGC
  89. 'ConcurrentMarkSweep',
  90. // Oracle (BEA) JRockit
  91. // -XgcPrio:pausetime
  92. 'Garbage collection optimized for short pausetimes Old Collector',
  93. // -XgcPrio:throughput
  94. 'Garbage collection optimized for throughput Old Collector',
  95. // -XgcPrio:deterministic
  96. 'Garbage collection optimized for deterministic pausetimes Old Collector'
  97. ]
  98. static int getYoungGCCount() {
  99. ManagementFactory.garbageCollectorMXBeans.inject(0) { youngGCCount, gc ->
  100. if (YoungGenCollectorNames.contains(gc.name))
  101. youngGCCount + gc.collectionCount
  102. else
  103. youngGCCount
  104. }
  105. }
  106. static int getFullGCCount() {
  107. ManagementFactory.garbageCollectorMXBeans.inject(0) { fullGCCount, gc ->
  108. if (OldGenCollectorNames.contains(gc.name))
  109. fullGCCount + gc.collectionCount
  110. else
  111. fullGCCount
  112. }
  113. }
  114. }
    import java.lang.management.ManagementFactory class GCStats { static final List YoungGenCollectorNames = [ // Oracle (Sun) HotSpot // -XX:+UseSerialGC 'Copy', // -XX:+UseParNewGC 'ParNew', // -XX:+UseParallelGC 'PS Scavenge', // Oracle (BEA) JRockit // -XgcPrio:pausetime 'Garbage collection optimized for short pausetimes Young Collector', // -XgcPrio:throughput 'Garbage collection optimized for throughput Young Collector', // -XgcPrio:deterministic 'Garbage collection optimized for deterministic pausetimes Young Collector' ] static final List OldGenCollectorNames = [ // Oracle (Sun) HotSpot // -XX:+UseSerialGC 'MarkSweepCompact', // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting) 'PS MarkSweep', // -XX:+UseConcMarkSweepGC 'ConcurrentMarkSweep', // Oracle (BEA) JRockit // -XgcPrio:pausetime 'Garbage collection optimized for short pausetimes Old Collector', // -XgcPrio:throughput 'Garbage collection optimized for throughput Old Collector', // -XgcPrio:deterministic 'Garbage collection optimized for deterministic pausetimes Old Collector' ] static int getYoungGCCount() { ManagementFactory.garbageCollectorMXBeans.inject(0) { youngGCCount, gc -> if (YoungGenCollectorNames.contains(gc.name)) youngGCCount + gc.collectionCount else youngGCCount } } static int getFullGCCount() { ManagementFactory.garbageCollectorMXBeans.inject(0) { fullGCCount, gc -> if (OldGenCollectorNames.contains(gc.name)) fullGCCount + gc.collectionCount else fullGCCount } } } 用的时候: Groovysh代码 收藏代码

  115. D:>\sdk\groovy-1.7.2\bin\groovysh

  116. Groovy Shell (1.7.2, JVM: 1.6.0_20)
  117. Type 'help' or '\h' for help.

  118. groovy:000> GCStats.fullGCCount
  119. ===> 0
  120. groovy:000> System.gc()
  121. ===> null
  122. groovy:000> GCStats.fullGCCount
  123. ===> 1
  124. groovy:000> System.gc()
  125. ===> null
  126. groovy:000> System.gc()
  127. ===> null
  128. groovy:000> GCStats.fullGCCount
  129. ===> 3
  130. groovy:000> GCStats.youngGCCount
  131. ===> 9
  132. groovy:000> GCStats.youngGCCount
  133. ===> 9
  134. groovy:000> GCStats.youngGCCount
  135. ===> 9
  136. groovy:000> System.gc()
  137. ===> null
  138. groovy:000> GCStats.youngGCCount
  139. ===> 9
  140. groovy:000> GCStats.fullGCCount
  141. ===> 4
  142. groovy:000> quit
    D:>\sdk\groovy-1.7.2\bin\groovysh Groovy Shell (1.7.2, JVM: 1.6.0_20) Type 'help' or '\h' for help. -------------------------------------------------- groovy:000> GCStats.fullGCCount ===> 0 groovy:000> System.gc() ===> null groovy:000> GCStats.fullGCCount ===> 1 groovy:000> System.gc() ===> null groovy:000> System.gc() ===> null groovy:000> GCStats.fullGCCount ===> 3 groovy:000> GCStats.youngGCCount ===> 9 groovy:000> GCStats.youngGCCount ===> 9 groovy:000> GCStats.youngGCCount ===> 9 groovy:000> System.gc() ===> null groovy:000> GCStats.youngGCCount ===> 9 groovy:000> GCStats.fullGCCount ===> 4 groovy:000> quit 这是在Sun JDK 6 update 20上跑的。顺带一提,如果这是跑在JRockit上的话,那full GC的次数就不会增加——因为JRockit里System.gc()默认是触发young GC的;请不要因为Sun HotSpot的默认行为而认为System.gc()总是会触发full GC的。 关于JMX的MXBean的使用,也可以参考下面两篇文档: Groovy and JMX Monitoring the JVM Heap with JRuby 如何更快的启动eclipse

评论 共 1 条 请登录后发表评论

1 楼 xgj1988 2011-04-27 15:07

SUN jdk 使用FULL GC 是如下的几种之一? Java代码 收藏代码

  1. static final List OldGenCollectorNames = [
  2. // Oracle (Sun) HotSpot
  3. // -XX:+UseSerialGC
  4. 'MarkSweepCompact',
  5. // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting)
  6. 'PS MarkSweep',
  7. // -XX:+UseConcMarkSweepGC
  8. 'ConcurrentMarkSweep',
  9. ]
    static final List OldGenCollectorNames = [ // Oracle (Sun) HotSpot // -XX:+UseSerialGC 'MarkSweepCompact', // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting) 'PS MarkSweep', // -XX:+UseConcMarkSweepGC 'ConcurrentMarkSweep', ] 这几个是young gc? Java代码 收藏代码

  10. 'Copy',

  11. // -XX:+UseParNewGC
  12. 'ParNew',
  13. // -XX:+UseParallelGC
  14. 'PS Scavenge',
  15. 'Copy', // -XX:+UseParNewGC 'ParNew', // -XX:+UseParallelGC 'PS Scavenge', 根据名字判断来获取full gc

    发表评论

您还没有登录,请您登录后再发表评论

New-page

文章信息

知识库: 高级语言虚拟机

相关讨论

© 2003-2012 ITeye.com. [ 京ICP证110151号 京公网安备110105010620 ] 百联优力(北京)投资有限公司 版权所有

希望本站内容对您有点用处,有什么疑问或建议请在后面留言评论
转载请注明作者(RobinChia)和出处 It so life ,请勿用于任何商业用途
本文链接: 通过Java