可读的JVM GC时间戳

当我们诊断Java应用程序的问题时,能够查到垃圾回收的状况是非常有帮助的。一个基本的最基础的方法是开启垃圾回收日志。

也许你已经知道了,如果我们把下面的参数加到java启动命令行中,

-Xloggc:<file_name> –XX:+PrintGCDetails -XX:+PrintGCDateStamps

JVM就会将垃圾回收信息写到-Xloggc设置的文件中。日志格式如下:

2010-04-22T18:12:27.796+0200: 22.317: [GC 59030K->52906K(97244K), 0.0019061 secs]
2010-04-22T18:12:27.828+0200: 22.348: [GC 59114K->52749K(97244K), 0.0021595 secs]
2010-04-22T18:12:27.859+0200: 22.380: [GC 58957K->53335K(97244K), 0.0022615 secs]
2010-04-22T18:12:27.890+0200: 22.409: [GC 59543K->53385K(97244K), 0.0024157 secs]

加粗的部分显示了垃圾回收时间的开始日期及时间。

不幸的是-XX:+PrintGCDateStamps参数只有Java 6u4及以后版本的JVM才可用。所以,如果我们很不幸而且我们的应用程序跑在就版本的JVM上,我们就被迫使用,

-Xloggc:<file> –XX:+PrintGCDetails

这样,得到的垃圾回收信息如下:

22.317: [GC 59030K->52906K(97244K), 0.0019061 secs]
22.348: [GC 59114K->52749K(97244K), 0.0021595 secs]
22.380: [GC 58957K->53335K(97244K), 0.0022615 secs]
22.409: [GC 59543K->53385K(97244K), 0.0024157 secs]

现在,加粗的数字表示从JVM启动时间开始的秒间隔。

这种情况下就很难把GC事件和其他日志文件中的信息关联到一起了:(

有没有简单的办法来处理gc日志文件并从秒间隔中关联出日期和时间呢?看起来是可以的,但是秒间隔从什么时候开始呢?换句话说,我们怎么得知JVM的启动日期和时间呢?

为了使用最最基础的方法,我们应该从同一个GC日志文件中分析出日期和时间。这样我们就要用到文件的属性了。我们有如下不同的选择:

UnixWindows
Access timeAccess time
Change timeCreation time
Modify timeModify time

我们抛弃掉access time、cheng time及creation time,因为他们不是在所有平台上都可用的。这样我们只剩下修改时间(modify time),表示文件最后一次修改的时间。

在Windows上,当文件被拷贝到其他地方时,修改时间是保持不变的。但是当我们在Unix上拷贝GC日志文件时,我们需要使用-p选项来保持时间戳属性

GC日志文件的最后修改时间应该和日志文件中最后一个记录的GC时间的时间戳保持一致。好吧,更精确点,由于日志行是在GC执行时一点一点写的,最后修改时间应该是确切等于最后的秒间隔加上GC的执行时间。

22.409: [GC 59543K->53385K(97244K), 0.0024157 secs]


在我们的方法中由于不需要精确时间,我们抛弃执行时间,进而得到每次垃圾回收时间发生的粗略时间。然而,我们必须注意在大的heap中,有时间GC的执行时间可以长达几秒。

当我们最近在一个客户那里体验这个方案时,我们需要快速开发一个简单的轻便的脚本,所以就选择Python来实现这个功能。你已经知道了我们不仅仅用Java吧。大笑


    
    
[python] view plain copy
  1. #!/usr/bin/env python  
  2.    
  3. import sys, os, datetime  
  4.    
  5. # true if string is a positive float  
  6. def validSeconds(str_sec):  
  7.     try:  
  8.         return 0 < float(str_sec)  
  9.     except ValueError:  
  10.         return False  
  11.    
  12. # show usage                  
  13. if len(sys.argv) < 2:  
  14.     print "Usage: %s <gc.log>" % (sys.argv[0])  
  15.     sys.exit(1)  
  16.    
  17. file_str = sys.argv[1]  
  18. lastmod_date = datetime.datetime.fromtimestamp(os.path.getmtime(file_str))  
  19.    
  20. file = open(file_str, 'r')  
  21. lines = file.readlines()  
  22. file.close()  
  23.    
  24. # get last elapsed time  
  25. for line in reversed(lines):  
  26.     parts = line.split(':')  
  27.     if validSeconds(parts[0]):  
  28.         break  
  29.    
  30. # calculate start time  
  31. start_date = lastmod_date - datetime.timedelta(seconds=float(parts[0]))  
  32.    
  33. # print file prepending human readable time where appropiate    
  34. for line in lines:  
  35.     parts = line.split(':')  
  36.     if not validSeconds(parts[0]):  
  37.         print line.rstrip()  
  38.         continue  
  39.     line_date = start_date + datetime.timedelta(seconds=float(parts[0]))  
  40.     print "%s: %s" % (line_date.isoformat(), line.rstrip())  

这个脚本的输出可以重定向到另一个文件中,在哪里可以得到:

2010-04-22T18:12:27.796375: 22.317: [GC 59030K->52906K(97244K), 0.0019061 secs]
2010-04-22T18:12:27.828375: 22.348: [GC 59114K->52749K(97244K), 0.0021595 secs]
2010-04-22T18:12:27.859375: 22.380: [GC 58957K->53335K(97244K), 0.0022615 secs]
2010-04-22T18:12:27.890375: 22.409: [GC 59543K->53385K(97244K), 0.0024157 secs]


你可能注意到了日期的格式并不是和-XX:+PrintGCDateStamps参数100%的一致。但这足以看出每个GC时间发生的时间。


原文:http://www.theserverlabs.com/blog/2010/05/26/human-readable-jvm-gc-timestamps/

PS:翻译这篇blog主要是想和大家分享这个python脚本,非常的使用。在运维类似于Hadoop这样的分布式大集群试,master的GC日志是一定要打开,因为各种各样的问题都可能和GC有关。但由于某些原因,如JDK版本或历史原因,可能配置了–XX:+PrintGCDetails而不是-XX:+PrintGCDateStamps,这样就非常需要本文的脚本来转换时间格式。当然最好是配上-XX:+PrintGCDateStamps参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值