jvm系列:Java GC 分析

Java GC就是JVM记录仪,书画了JVM各个分区的表演。html

什么是 Java GC

Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,做为Java开发者,通常不须要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不须要像C程序员那样战战兢兢。这是由于在Java虚拟机中,存在自动内存管理和垃圾清扫机制。归纳地说,该机制对JVM(Java Virtual Machine)中的内存进行标记,并肯定哪些内存须要回收,根据必定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。java

在Java语言出现以前,就有GC机制的存在,如Lisp语言),Java GC机制已经日臻完善,几乎能够自动的为咱们作绝大多数的事情。然而,若是咱们从事较大型的应用软件开发,曾经出现过内存优化的需求,就一定要研究Java GC机制。程序员

简单总结一下,Java GC就是经过GC收集器回收不在存活的对象,保证JVM更加高效的运转。若是不了解GC算法和垃圾回收器能够参考这篇文章:jvm系列(三):GC算法 垃圾收集器web

如何获取 Java GC日志

通常状况能够经过两种方式来获取GC日志,一种是使用命令动态查看,一种是在容器中设置相关参数打印GC日志。算法

命令动态查看

Java 自动的工具行命令,jstat能够用来动态监控JVM内存的使用,统计垃圾回收的各项信息。tomcat

好比经常使用命令,jstat -gc 统计垃圾回收堆的行为并发

$ jstat -gc 1262
 S0C    S1C     S0U     S1U   EC       EU        OC         OU        PC       PU         YGC    YGCT    FGC    FGCT     GCT   
26112.0 24064.0 6562.5  0.0   564224.0 76274.5   434176.0   388518.3  524288.0 42724.7    320    6.417   1      0.398    6.815复制代码

也能够设置间隔固定时间来打印:less

$ jstat -gc 1262 2000 20复制代码

这个命令意思就是每隔2000ms输出1262的gc状况,一共输出20次jvm

更详细的内容参考这篇文章:jvm系列(四):jvm调优-命令篇工具

GC参数

JVM的GC日志的主要参数包括以下几个:

  • -XX:+PrintGC 输出GC日志
  • -XX:+PrintGCDetails 输出GC的详细日志
  • -XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
  • -XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2017-09-04T21:53:59.234+0800)
  • -XX:+PrintHeapAtGC 在进行GC的先后打印出堆的信息
  • -Xloggc:../logs/gc.log 日志文件的输出路径

在生产环境中,根据须要配置相应的参数来监控JVM运行状况。

Tomcat 设置示例

咱们常常在tomcat的启动参数中添加JVM相关参数,这里有一个典型的示例:

JAVA_OPTS="-server -Xms2000m -Xmx2000m -Xmn800m -XX:PermSize=64m -XX:MaxPermSize=256m -XX:SurvivorRatio=4 -verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log -Djava.awt.headless=true -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Dsun.rmi.dgc.server.gcInterval=600000 -Dsun.rmi.dgc.client.gcInterval=600000 -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15"复制代码

根据上面的参数咱们来作一下解析:

  • -Xms2000m -Xmx2000m -Xmn800m -XX:PermSize=64m -XX:MaxPermSize=256m
    Xms,即为jvm启动时得JVM初始堆大小,Xmx为jvm的最大堆大小,xmn为新生代的大小,permsize为永久代的初始大小,MaxPermSize为永久代的最大空间。

  • -XX:SurvivorRatio=4
    SurvivorRatio为新生代空间中的Eden区和救助空间Survivor区的大小比值,默认是8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。调小这个参数将增大survivor区,让对象尽可能在survitor区呆长一点,减小进入年老代的对象。去掉救助空间的想法是让大部分不能立刻回收的数据尽快进入年老代,加快年老代的回收频率,减小年老代暴涨的可能性,这个是经过将-XX:SurvivorRatio 设置成比较大的值(好比65536)来作到。

  • -verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log
    将虚拟机每次垃圾回收的信息写到日志文件中,文件名由file指定,文件格式是平文件,内容和-verbose:gc输出内容相同。

  • -Djava.awt.headless=true
    Headless模式是系统的一种配置模式。在该模式下,系统缺乏了显示设备、键盘或鼠标。

  • -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
    设置gc日志的格式

  • -Dsun.rmi.dgc.server.gcInterval=600000 -Dsun.rmi.dgc.client.gcInterval=600000
    指定rmi调用时gc的时间间隔

  • -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15
    采用并发gc方式,通过15次minor gc 后进入年老代

如何分析GC日志

摘录GC日志一部分

Young GC回收日志:

2016-07-05T10:43:18.093+0800: 25.395: [GC [PSYoungGen: 274931K->10738K(274944K)] 371093K->147186K(450048K), 0.0668480 secs] [Times: user=0.17 sys=0.08, real=0.07 secs]复制代码

Full GC回收日志:

2016-07-05T10:43:18.160+0800: 25.462: [Full GC [PSYoungGen: 10738K->0K(274944K)] [ParOldGen: 136447K->140379K(302592K)] 147186K->140379K(577536K) [PSPermGen: 85411K->85376K(171008K)], 0.6763541 secs] [Times: user=1.75 sys=0.02, real=0.68 secs]复制代码

经过上面日志分析得出,PSYoungGen、ParOldGen、PSPermGen属于Parallel收集器。其中PSYoungGen表示gc回收先后年轻代的内存变化;ParOldGen表示gc回收先后老年代的内存变化;PSPermGen表示gc回收先后永久区的内存变化。young gc 主要是针对年轻代进行内存回收比较频繁,耗时短;full gc 会对整个堆内存进行回城,耗时长,所以通常尽可能减小full gc的次数

经过两张图很是明显看出gc日志构成:

Young GC日志:

Full GC日志:

GC分析工具

GChisto

GChisto是一款专业分析gc日志的工具,能够经过gc日志来分析:Minor GC、full gc的时间、频率等等,经过列表、报表、图表等不一样的形式来反应gc的状况。虽然界面略显粗糙,可是功能仍是不错的。

配置好本地的jdk环境以后,双击GChisto.jar,在弹出的输入框中点击 add 选择gc.log日志

  • GC Pause Stats:能够查看GC 的次数、GC的时间、GC的开销、最大GC时间和最小GC时间等,以及相应的柱状图

  • GC Pause Distribution:查看GC停顿的详细分布,x轴表示垃圾收集停顿时间,y轴表示是停顿次数。

  • GC Timeline:显示整个时间线上的垃圾收集

不过这款工具已经再也不维护

GC Easy

这是一个web工具,在线使用很是方便.

地址: gceasy.io

进入官网,讲打包好的zip或者gz为后缀的压缩包上传,过一会就会拿到分析结果。

推荐使用此工具进行gc分析。


喜欢个人文章,请关注个人公众号

相关文章
相关标签/搜索