`
RednaxelaFX
  • 浏览: 3047829 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

用Java获取full GC的次数?(2)

    博客分类:
  • Java
阅读更多
接着上一帖,再谈谈一个Java进程要获取自己的full GC次数的方法,同样是高度平台相关的办法。

大家如果熟悉JDK 6的内建工具,或许已经知道可以通过jstat工具很轻松的从外部得知一个Java进程的GC统计信息,其中就包括了full GC的次数。
假定我们相信jstat的数据是准确的,那么只要跟它从同一来源获取数据就可以保证我们拿到正确的full GC次数信息了。
查看OpenJDK 6中jstat的一个源文件,jdk/src/share/classes/sun/tools/jstat/resources/jstat_options,可以看到jstat -gcutil输出的YGC(young GC)与FGC(full GC)值分别是从下面两个定义而来的:
column {
  header "^YGC^"	/* Young Generation Collections */
  data sun.gc.collector.0.invocations
  align right
  width 6
  format "0"
}
column {
  header "^FGC^"	/* Full Collections */
  data sun.gc.collector.1.invocations
  align right
  width 5
  scale raw
  format "0"
}

也就是说,在Oracle (Sun) HotSpot上,通过jvmstat API,找到名字为 "sun.gc.collector.0.invocations""sun.gc.collector.1.invocations"Monitor对象,我们就可以拿到YGC与FGC对应的值了。别的JVM即便支持该API,Monitor的名字也可能会不同;在Oracle (BEA) JRockit R28上,两者对应的名字分别为 "jrockit.gc.latest.yc.number""jrockit.gc.latest.oc.number"

在底层,HotSpot通过perfData接口来提供这些数据;注册数据的实现在services目录里。

OpenJDK官网上也有一个相关文档:HotSpot Jvmstat Performance Counters

提一下jvmstat文档上说的一个注意点:
引用
The instrumented HotSpot JVM exports a set of instrumentation objects, or counters as they are typically called. The set of counters exported by a JVM is not static, as a JVM may create certain counters only when appropriate arguments are specified on the command line. Furthermore, different versions of a JVM may export very different sets of instrumentation. The names of these counters and the data structures used to represent them are considered private, uncommitted interfaces to the HotSpot JVM. Users should not become dependent on any counter names, particularly those that start with prefixes other than "java.".

也就是说我们最好别依赖这些计数器的名字。不过反正这帖只是介绍些hack的办法而已,不管了 

下面用Groovy代码来演示一下。
使用jvmstat API需要指定vmid,对多数系统上本地Java进程的VMID就是PID。这里正好用上以前一帖介绍的获取进程自己的PID的方式。

import java.lang.management.ManagementFactory
import sun.jvmstat.monitor.*;

class Runtimes {
  static int getOwnPid() {
    def name = ManagementFactory.runtimeMXBean.name
    name[0..<name.indexOf('@')] as int
  }
}

class GCStats {
  // Oracle (Sun) HotSpot
  static final String YOUNG_GC_MONITOR_NAME = 'sun.gc.collector.0.invocations'
  static final String FULL_GC_MONITOR_NAME  = 'sun.gc.collector.1.invocations'
  
  // Oracle (BEA) JRockit
  // static final String YOUNG_GC_MONITOR_NAME = 'jrockit.gc.latest.yc.number'
  // static final String FULL_GC_MONITOR_NAME  = 'jrockit.gc.latest.oc.number'
  
  static final Monitor youngGCMonitor;
  static final Monitor fullGCMonitor;
  
  static {
    def vmId     = new VmIdentifier(Runtimes.ownPid as String)
    def interval = 0
    def monitoredHost = MonitoredHost.getMonitoredHost(vmId)
    def monitoredVm = monitoredHost.getMonitoredVm(vmId, interval)
    youngGCMonitor = monitoredVm.findByName(YOUNG_GC_MONITOR_NAME)
    fullGCMonitor = monitoredVm.findByName(FULL_GC_MONITOR_NAME)
  }
  
  static int getYoungGCCount() {
    youngGCMonitor.value
  }
  
  static int getFullGCCount() {
    fullGCMonitor.value
  }
}

可以看到,要获取young GC与full GC次数的读数很简单,找到合适的Monitor对象后,每次读一下value属性就好了。
在Groovy shell里演示一下使用情况,在Sun JDK 6 update 20/Windows XP SP3上跑:
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(); System.gc(); System.gc()
===> null
groovy:000> GCStats.fullGCCount
===> 4
groovy:000> GCStats.youngGCCount
===> 9
groovy:000> System.gc(); System.gc(); System.gc()
===> null
groovy:000> GCStats.youngGCCount
===> 9
groovy:000> GCStats.fullGCCount
===> 7
groovy:000> quit


这次也顺便演示一下在Oracle JRockit R28/Windows XP SP3上跑:
D:\>\sdk\groovy-1.7.2\bin\groovysh
Groovy Shell (1.7.2, JVM: 1.6.0_17)
Type 'help' or '\h' for help.
--------------------------------------------------
groovy:000> GCStats
===> class GCStats
groovy:000> GCStats.youngGCCount
===> 1
groovy:000> System.gc()
===> null
groovy:000> GCStats.youngGCCount
===> 2
groovy:000> System.gc(); System.gc(); System.gc()
===> null
groovy:000> GCStats.youngGCCount
===> 5
groovy:000> GCStats.fullGCCount
===> 0
groovy:000> quit

可以看到System.gc()引发的是young GC而不是full GC吧? ^_^
分享到:
评论
4 楼 RednaxelaFX 2010-12-04  
IcyFenix 写道
呃,原来你下一篇博客已经写了这个事,刚才没看到 = =#

是上一篇…这个系列的第一篇是写JMX的,这个是第二篇,我正好心情好所以讲点hack的办法 >_<
3 楼 IcyFenix 2010-12-04  
呃,原来你下一篇博客已经写了这个事,刚才没看到 = =#
2 楼 RednaxelaFX 2010-12-04  
那个…上一篇不就是用JMX来获取这种信息的么。另外System.gc()引发的GC种类我也根据具体实现来分开说明了,如果对此有疑问的话欢迎探讨,HotSpot这边我可以把源码找来说明它是触发full GC(或者是完全不引发GC,根据启动参数决定);JRockit是文档上写着引发minor GC的。
1 楼 IcyFenix 2010-12-04  
撒加同学,我觉得取YGC和FGC次数,没有必要引jvmstat的类进来,jvmstat里面也是根据jmx开放的mbean来找gc次数的直接从jmx里面拿还省掉去找自己的pid,和平台也不用咬得那么死。下面的代码以ps/ps old收集器为例子,直接从mbean取gc次数:

package org.fenixsoft.jmx;

import java.lang.management.ManagementFactory;

import javax.management.MBeanServer;
import javax.management.ObjectName;

public class MBeanAccess {
	public static void main(String[] args) throws Exception {
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		ObjectName youngMBean = new ObjectName("java.lang:type=GarbageCollector,name=PS MarkSweep");
		ObjectName tenuredMBean = new ObjectName("java.lang:type=GarbageCollector,name=PS Scavenge");
		System.out.println("YGC:" + mbs.getAttribute(youngMBean, "CollectionCount"));
		System.out.println("FGC:" + mbs.getAttribute(tenuredMBean, "CollectionCount"));
		System.gc();
		System.out.println("YGC:" + mbs.getAttribute(youngMBean, "CollectionCount"));
		System.out.println("FGC:" + mbs.getAttribute(tenuredMBean, "CollectionCount"));
	}
}


另外,System.gc()引发哪种gc这个不是一概而论的吧。

相关推荐

    java应用JVM的GC频率观察方法

    此外,可以使用`-Xloggc:gc.log`指定日志输出文件,然后通过工具如GCViewer进行日志分析,以获取更直观的GC行为可视化。 2. 在生产环境下,由于直接修改JVM参数可能影响线上服务,因此通常推荐使用专门的监控工具。...

    gcviewer监控gc工具

    3. **统计信息**:提供详细的统计信息,如平均GC时间、总GC次数、暂停时间等,帮助量化评估系统性能。 4. **自定义配置**:用户可以根据需求自定义日志解析规则,适应不同JVM配置下的日志格式。 四、使用步骤 1. **...

    gchisto - gc

    2. **Young GC次数**:年轻代GC是指只清理新生代(New Generation)内存区域的GC。新生代通常包含最近创建的对象,频繁进行小规模的GC以保持这部分内存的高效利用。 3. **Full GC次数**:全GC涉及整个堆(包括...

    并发串行GC上传GCEasy的诊断图1

    分别对年轻代(Minor GC)、老年代(Full GC)的GC活动进行了单独分析,包括GC次数、回收字节数、总耗时、平均耗时以及最小/最大耗时。 通过对这些数据的深入分析,可以识别出Java应用程序中的内存使用模式、垃圾...

    GChisto GC日志分析工具

    2. **获取GC日志**: 首先确保Java应用配置了生成GC日志,通常在JVM启动参数中添加`-XX:+PrintGC`和`-XX:+PrintGCDetails`选项。 3. **运行GChisto**: 在解压后的目录中,双击`GChisto.jar`文件,启动工具。 4. **...

    实战Hot Spot JVM GC

    这些工具可以帮助开发者监控JVM的运行状态,包括GC的次数和时间、内存使用情况等。 jstat命令提供了一个强大的工具用于监控Java虚拟机中的堆使用情况和GC的状态。使用例如"-gccapacity"、"-gccause"、"-gcutil"等...

    java内存动态编译执行

    元空间的大小可以动态调整,避免了永久代因空间不足导致的Full GC问题。 6. **G1垃圾收集器与动态编译**: G1垃圾收集器是Java 9默认的垃圾收集器,它在进行垃圾回收时,会考虑JIT编译的影响,避免在编译过程中...

    GCLogViewer-0.3-win64

    此外,还有详细的统计信息,如总GC次数、平均GC耗时等,这些数据对于调优是非常有价值的。 GCLogViewer还支持比较不同时间段或不同环境下的GC日志,这样可以对比分析不同配置或优化策略对GC行为的影响。通过这种...

    JVM常见面试题解析,面试一路绿灯

    2. Java虚拟机栈:存放基本数据类型、对象引用和方法出口,也是线程私有。 3. Native方法栈:服务于Native方法,与虚拟机栈类似,线程私有。 4. Java堆:存储所有对象实例和数组,是Java内存中最大的一块,也是垃圾...

    游戏行业JAVA初级面试题

    - 以下哪些情况会产生Full GC:**持久代被写满**和**显式调用System.gc()**(D正确,年轻代和年老代被写满会导致Minor GC和Major GC,而不是Full GC)。 - Checked Exception包括**ClassNotFoundException**和**...

    JVM下篇:性能监控与调优篇.7z

    - **Full GC次数**:频繁的Full GC会导致应用暂停时间过长。 - **线程状态**:分析阻塞、等待和死锁等问题。 - **类加载情况**:过多的类加载可能占用大量内存。 6. **调优策略**: - **根据应用特点选择合适的...

    java高级工程师面试题

    - **Full GC**: 在老年代空间不足或系统检测到内存压力较大时触发,涉及整个堆空间及方法区的垃圾回收。 - **GC调优**: 通过调整新生代和老年代的比例来优化性能。默认比例为1:2,可以通过参数调整以适应不同的...

    查看虚拟机状态常用命令

    - **FGC/FGCT**: Full GC的次数与总时间。 - **GCT**: 总的GC时间。 - **`jstat -gc &lt;vmid&gt;`**: 显示GC统计信息。 - **S0C/S1C**: 第一个/第二个Survivor Space的大小。 - **S0U/S1U**: 第一个/第二个Survivor...

    resin-jvm 调优

    1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。...一般的标准是减少fullgc的次数,最好硬件支持使用并行垃圾回收(要求多CPU)。

    性能学习报告

    - `FGC`:从应用程序启动到采样时发生Full GC的次数。 - `FGCT`:从应用程序启动到采样时Full GC所用的时间(单位秒)。 - `GCT`:从应用程序启动到采样时用于垃圾回收的总时间(单位秒)。 ##### 2. 关注指标 -...

    后端开发基础知识整理JAVA、JVM、操作系统、网络、设计模式、mysql、redis、多线程、spring、springboo

    - **Minor GC、Major GC、Full GC**:分别表示年轻代、老年代、整个堆的垃圾回收。 - **类文件结构**:包括魔数、版本号、常量池等部分。 - **User user = new User()做了什么操作**:分配内存、初始化对象等。 - **...

    JVM 45道面试题和答案.docx

    - Full GC:全堆垃圾回收,涉及年轻代和老年代,通常较慢。 9. 对象分配: - 年轻代是默认分配区域,但如果年轻代空间不足,大对象或经过多次晋升的对象会直接分配在老年代。 10. 不同的垃圾收集器: - Serial...

Global site tag (gtag.js) - Google Analytics