GC日志分析
阅读GC日志是处理Java虚拟机内存问题的基础技能,它是一些人为确定的规则,没什么太多技术含量. GC日志可以使用很多工具看到.下面是将日志输出到本地磁盘的文件夹中.
1.首先了解一下基础的JVM参数
-Xms:初始堆大小,默认为物理内存的1/64(<1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx 的最大限制 -Xmx:堆的最大空间大小。默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制 -XX:NewSize 新生代最小空间大小。 -XX:MaxNewSize 新生代最大空间大小。 -XX:PermSize 设置永久代(perm gen)初始值。默认值为物理内存的1/64 -XX:MaxPermSize 设置持久代最大值。物理内存的1/4。 -Xss:每个线程的堆栈大小, JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。应根据应用的线程所 需内存大小进行适当调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是 有限制的,不能无限生成,经验值在3000~5000左右。一般小的应用, 如果栈不是很深, 应该是128k够用的,大的应 用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎 没有解释,在论坛中有这样一句话:”-Xss is translated in a VM flag named ThreadStackSize”一般设置这 个值就可以了。 -Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=新生代大小 + 老生代大小 + 永久代大小。 在保证堆大小不变的情况下,增大新生代后, 将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。 -XX:SurvivorRatio:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。
2.D盘创建一个 GClogs文件夹,启动idea,随便写个小demo
使用一下<<深入理解JVM>>书中的例子
public class TestGcDemo { private static final int _1MB = 1024 * 1024; //定义常量1MB大小 /* * vm参数: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails * -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:d:/GClogs/tomcat8-gc.log * */ public static void main(String[] args) { byte[] allocation1, allocation2, allocation3, allocation4; allocation1 = new byte[2 * _1MB]; allocation2 = new byte[2 * _1MB]; allocation3 = new byte[2 * _1MB]; allocation4 = new byte[4 * _1MB]; //出现一次minorGc System.out.println("-----------end------------"); } }
Window下idea的VM参数设置如下,tomcat7-gc.log表示输出日志到这个文件里面
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:d:/GClogs/tomcat7-gc.log
然后运行一下代码,找到d:/GClogs/tomcat7-gc.log文件
3.选一个分析一下
0.177: [GC (Allocation Failure) [PSYoungGen: 6666K->799K(9216K)] 6666K->4903K(19456K), 0.0119057 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
0.177 表示GC发生时间,即从Java虚拟机启动以来经过的秒数;
[GC 表示 垃圾收集的停顿类型,若前面有Full则表明是Full GC,没有Full的修饰表明这是一次Minor GC 。注意它不表示只GC新生代;
Allocation Failure 括号里的内容是gc发生的原因,这里的Allocation Failure的原因是年轻代中没有足够区域能够存放需要分配的数据而失败;
PSYoungGen表示GC发生区域
6666K表示 GC前该内存区域已使用容量
799K表示 GC后该内存区域已使用容量
9216K表示 该内存区域总容量
6666K表示 GC前Java堆已使用容量
4903K表示 GC后Java堆已使用容量
19456K表示 GC前Java堆总容量
0.0119057 secs表示 改内存区域GC占用时间,单位是秒
user/sys/real 表示 分别代表用户态消耗的CPU时间,内核态消耗的CPU时间和操作从开始到结束锁经过的墙钟时间.
4.再补一个内存模型
(上图出处:https://blog.csdn.net/qq_19734597/article/details/80958817)