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

什么是 Java GC

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

在Java语言出现之前,就有GC机制的存在,如Lisp语言),Java GC机制已经日臻完善,几乎可以自动的为我们做绝大多数的事情。然而,如果我们从事较大型的应用软件开发,曾经出现过内存优化的需求,就必定要研究Java GC机制。

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

如何获取 Java GC日志

一般情况可以通过两种方式来获取GC日志,一种是使用命令动态查看,一种是在容器中设置相关参数打印GC日志。

命令动态查看

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

比如常用命令,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

也可以设置间隔固定时间来打印:

$ jstat -gc 1262 2000 20

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

更详细的内容参考这篇文章: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工具,在线使用非常方便.

地址: http://gceasy.io

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

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

jvm系列(五):Java GC 分析的更多相关文章

  1. jvm系列(九):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  2. JVM系列(五):gc实现概要01

    java的一大核心特性,即是自动内存回收.这让一些人从繁琐的内存管理中解脱出来,但对大部分人来说,貌似这太理所当然了.因为现在市场上的语言,几乎都已经没有了还需要自己去管理内存这事.大家似乎都以为,语 ...

  3. jvm系列(三):java GC算法 垃圾收集器

    GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...

  4. jvm系列五-java内存模型(2)

    原作者系列文章链接:并发编程系列博客传送门 前言# 在网上看了很多文章,也看了好几本书中关于JMM的介绍,我发现JMM确实是Java中比较难以理解的概念.网上很多文章中关于JMM的介绍要么是照搬了一些 ...

  5. jvm系列五-java内存模型初览(1)

    本文转载自:再有人问你Java内存模型是什么,就把这篇文章发给他. 网上有很多关于Java内存模型的文章,在<深入理解Java虚拟机>和<Java并发编程的艺术>等书中也都有关 ...

  6. JVM系列五:JVM监测&工具

    JVM系列五:JVM监测&工具[整理中]  http://www.cnblogs.com/redcreen/archive/2011/05/09/2040977.html 前几篇篇文章介绍了介 ...

  7. jvm系列:Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  8. jvm系列(六):Java服务GC参数调优案例

    本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题. ...

  9. JVM系列五:JVM监测&工具[整理中]

    前几篇篇文章介绍了介绍了JVM的参数设置并给出了一些生产环境的JVM参数配置参考方案.正如之前文章中提到的JVM参数的设置需要根据应用的特性来进行设置,每个参数的设置都需要对JVM进行长时间的监测,并 ...

随机推荐

  1. MyBatis-Plus 使用说明介绍

    先看一下和MyBatis 不同点说明: @GetMapping("/select_sql") public Object getUserBySql() { User user=ne ...

  2. CentOS虚拟机查询jdk路径

    [root@wshCentOS ~]# which java/usr/bin/java[root@wshCentOS ~]# ls -lrt /usr/bin/javalrwxrwxrwx. 1 ro ...

  3. Python基础总结之第二天从变量开始(新手可相互督促)

    hhh 为年薪20万加油ヾ(◍°∇°◍)ノ゙ 一.变量:(变量的命名规则:一般使用字母开头,可以使用下划线连接,以及数字) 正确的变量命名示范:   (尽量使用容易理解什么用途的词语) a1   na ...

  4. windows上node开发注意事项

    windows上进行node.react开发的必要步骤: 1.使用nvm进行node及npm包管理工具,记得使用npm config set ...:2.另外react仅支持python3.0以下的版 ...

  5. jmeter Linux环境执行总报错 cannot allocate memory

    1.windows环境写好的测试用例,执行没有问题,在Linux环境跑总是报错,提示如下 cannot allocate memory 2.一开始以为是哪块设置有问题,因为脚本里边有设置邮件自动发送, ...

  6. Hadoop自学系列集(三) ---- Hadoop安装

    这节就开始讲述Hadoop的安装吧.在这之前先配置下SSH免密码登录,为什么需要配置这个呢?大家都知道Hadoop集群中可能有几十台机器甚至是上千台机器,而每次启动Hadoop都需要输入密码才能够登录 ...

  7. win10下nodejs的安装及配置

    这里主要引用两篇文章,写的非常详细,也能解决你可能出现的问题 nodejs安装及配置 如何删除之前nodejs设置的 npm config set prefix .....

  8. JDBC秒变C3P0连接池——再加连接解耦

    从JDBC连接到C3P0数据库连接池 在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");)   ② ...

  9. Vue监听键盘回车事件

    在写页面时遇见了登录页需要加一个键盘回车事件. vue 的 v-on中有这样的修饰符 <input v-on:keyup.enter="submit"> 即<in ...

  10. 实现API优先设计的重要性和实现方式

    应用API优先的方法意味着设计API时,使其具有一致性和适应性,无论应用于哪些开发项目.对API使用API​​描述语言(如OpenAPI)是关键,因为它有助于建立API与其他程序通信的枢纽,即使这些系 ...