jvm系列(九):Java GC 分析
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 分析的更多相关文章
- jvm系列(五):Java GC 分析
Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...
- jvm系列(三):java GC算法 垃圾收集器
GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...
- jvm系列:Java GC 分析
Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...
- jvm系列(六):Java服务GC参数调优案例
本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题. ...
- Java GC分析记录
Java GC记录 近来.项目没有特别忙碌的时候,抽空看了下生产环境的项目运行状况,我们的项目一直运行速度不是很快,偶尔会出现卡顿的现象,这点给人的体验感觉也就不那么好了.先抛个测试环境截图(生产环境 ...
- JVM学习--(八)java堆分析
上一节介绍了针对JVM的监控工具,包括JPS可以查看当前所有的java进程,jstack查看线程栈可以帮助你分析是否有死锁等情况,jmap可以导出java堆文件在MAT工具上进行分析等等.这些工具都非 ...
- JVM系列(五):gc实现概要01
java的一大核心特性,即是自动内存回收.这让一些人从繁琐的内存管理中解脱出来,但对大部分人来说,貌似这太理所当然了.因为现在市场上的语言,几乎都已经没有了还需要自己去管理内存这事.大家似乎都以为,语 ...
- jvm系列五-java内存模型(2)
原作者系列文章链接:并发编程系列博客传送门 前言# 在网上看了很多文章,也看了好几本书中关于JMM的介绍,我发现JMM确实是Java中比较难以理解的概念.网上很多文章中关于JMM的介绍要么是照搬了一些 ...
- jvm系列(一):java类的加载机制
java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...
随机推荐
- AngularJS简单入门
什么是AngularJS AngularJS是一款优秀的前端JS框架,是Google多款产品之一,简称ng. ng有着诸多特性,最为核心的是:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入 ...
- 如何加密 Windows VM 上的虚拟磁盘
为了增强虚拟机 (VM) 的安全性以及符合性,可以加密 Azure 中的虚拟磁盘. 磁盘是使用 Azure 密钥保管库中受保护的加密密钥加密的. 可以控制这些加密密钥,以及审核对它们的使用. 本文详细 ...
- 判断Exception类中是否有InnerException属性
public static class ExceptionExtend { /// <summary> /// 利用反射来判断对象是否包含某个属性 /// </summary> ...
- 【排序算法】选择排序(Selection sort)
0. 说明 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最 ...
- 【Vue.js学习】生命周期及数据绑定
一.生命后期 官网的图片说明: Vue的生命周期总结 var app = new Vue({ el:"#app", beforeCreate: function(){ consol ...
- Javaweb学习(二):Http通信协议
当我们开始jsp/servlet编程之旅之前,我们还需要知道一些关于网络通讯方面的一些知识.这样能更加有助于我们的理解,希望大家能看懂我的描述,而不至于在学习的路上一知半解.(手动比❤) 认识Ht ...
- T4学习- 1、简介
一.T4简介 T4(Text Template Transformation Toolkit)在 Visual Studio 中,"T4 文本模板"是由一些文本块和控制 ...
- windows 2012 抓明文密码方法
windows 2012 抓明文密码方法 默认配置是抓不到明文密码了,神器mimikatz显示Password为null Authentication Id : 0 ; 121279 (0000000 ...
- initialProps被React-Navigation的navigation属性覆盖解决方案
怎么开场对我来说一个是个很纠结的问题,Emmm这应该算个好开场. 最近在做一个RN的app端调试工具,在把它嵌入原生app中的时候遇到了一个问题,RN组件里面接受不到原生传过来的initialProp ...
- BZOJ4894:天赋(矩阵树定理)
Description 小明有许多潜在的天赋,他希望学习这些天赋来变得更强.正如许多游戏中一样,小明也有n种潜在的天赋,但有一些天赋必须是要有前置天赋才能够学习得到的. 也就是说,有一些天赋必须是要在 ...