Java GC
什么是Java GC
Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,一般不需要转本编写内存回收和垃圾清理代码,这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括的说,该机制对JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息的保证JVM中的内存空间,防止出现内存泄漏和溢出问题。
Java GC 就是通过GC收集器回收不再存活的对象,保证JVM更加高效的运转。
如何获取Java GC日志
一般情况可以通过两种方式来获取GC日志,一种是使用命令动态查看,一种是在容器中设置相关参数打印GC日志。
使用命令动态查看
jstat可以用来动态监控JVM内存的使用,统计垃圾回收的各项信息。比如常用命令:jstat -gc pid统计垃圾回收堆的行为

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

这个命令的意思就是每隔2000ms输出pid 17953的gc情况,一共输出20次。
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区的大小比值,默认是32,也就是说Eden区是Survivor区的32倍大小,要注意Survivo是分为两个区的。调小这个参数将增大survivor区,让对象尽量在survivor区待的久一些,减少进入老年代的对象。
-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次gc后进入到老年代。
如何分析GC日志
Young GC回收日志:
[GC [PSYoungGen: 274931K->10738K(274944K)] 371093K->147186K(450048K), 0.0668480 secs] [Times: user=0.17 sys=0.08, real=0.07 secs]
Full GC回收日志:
[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回收前后年轻代的内存变化;PerOldGen表示gc回收前后老年代的内存变化;PSPermGen表示gc会收钱前后永久代的内存变化。Young GC主要是针对年轻代进行内存回收比较频繁,耗时短;full gc会对整个堆内存进行回收,耗时长。因此一般尽量减少full gc的次数。

浙公网安备 33010602011771号