目录
java8垃圾收集器组合一览
我们知道,针对年轻代和年老代的垃圾回收需要采取不同的gc算法(因为年轻代的内存经常被回收,而年老代的内存很少被回收,根据这个特性所采取的的算法往往是不一样的)。
在java8中,针对年轻代和年老代的垃圾回收,java8采用垃圾收集器组成下列组合;
现在常用的垃圾收集器组合有4种(上图黑色字体加粗的):
- 年轻代和年老代使用串行gc(gc就是垃圾收集器garbage collection)
- 年轻代和年老代使用并行gc
- 年轻代使用并行gc,年老代使用并发标记清除垃圾收集器
- 年轻代和老年代使用G1垃圾收集器
serial GC(串行GC)的实现
串行gc对年轻代使用标记-复制算法(mark-copy),对年老代使用标记-清除-整理算法(mark-sweep-compact)。不管是年轻代还是年老代,在触发gc时都会导致全线暂停(STW)。所以串行gc的缺点是不能充分利用多核CPU,JVM在进行垃圾收集时都只能使用单核(不然为啥叫串行呢[doge])。
JVM让年轻代和年老代使用串行GC的指令如下:
java -XX:+UseSerialGC 你要执行的class文件
这个指令执行后项目的JVM就会采取串行GC的方式进行垃圾回收,我们需要打开GC日志进行分析所以启动指令改为:
java ‐XX:+PrintGCDetails ‐XX:+PrintGCDateStamps ‐XX:+PrintGCTimeStamps -XX:+UseSerialGC 你要执行的class文件
串行gc日志分析
接下来根据网上的gc日志图片学习一波gc日志分析
Minor GC(小型GC)
上面这个截图就是清理年轻代的gc事件,下面分析一波日志:
- 2015‐05‐26T14:45:37.987‐0200:GC事件的开始时间,-0200表示西二时区,中国所在的东8区是+0800.
- 151.126:GC事件开始时,相对于JVM启动时的间隔时间,单位秒。
- allocation Failure:触发GC的原因。即本次GC是由于年轻代中没有空间来存放新的数据接口引起的。
- DefNew:垃圾收集器在日志中的名称。DefNew表示在年轻代中使用单线程、标记复制算法,全线暂停的垃圾收集器。
- 629119K‐>69888K:在垃圾收集之前和之后年轻代的使用量。
- (629120K):年轻代总的空间大小。
- 1619346K‐>1273247K: 在垃圾收集之前和之后整个堆内存的使用情况。
- (2027264K): 可用堆的总空间大小。
- 0.0585007 secs: GC事件持续的时间,以秒为单位。
10.[Times: user=0.06 sys=0.00, real=0.06 secs] : GC事件的持续时间, 通过三个部分来衡量 ,user – 在此次垃圾回收过程中, 所有 GC线程所消耗的 CPU 时间之和。sys – GC过程中中操作系统调用和系统等待事件所消耗的时间。real – 应用程序暂停的时间。因为串行垃圾收集器(Serial Garbage Collector)只使用单线程, 因此 real time 等 于 user 和 system 时间的总和。
可以从上面的日志片段了解到, 在 GC事件中,JVM 的内存使用情况发生了怎样的变化。此次垃圾收集之前, 堆内存总 的使用量为 1,619,346K。其中,年轻代使用了 629,119K。可以算出,老年代使用量为 990,227K。 更重要的信息蕴含在下一批数字中, 垃圾收集之后, 年轻代的使用量减少了 559,231K, 但堆内存的总体使用量只下降 了 346,099K。 从中可以算出,有 213,132K 的对象从年轻代提升到了老年代。
Full GC(完全GC)
- Tenured: 用于清理老年代空间的垃圾收集器名称。Tenured 表明使用的是单线程的全线暂停垃圾收集 器, 收集算法为 标记清除整理(marksweepcompact )。
- [Metaspace: 6741K‐>6741K(1056768K)] : 关于 Metaspace 空间, 同样的信息。可以看出, 此次 GC过程 中 Metaspace
为什么说这个gc是full GC,因为由日志可知本次gc不仅清理的年轻代,还清理了年老代和元空间,根据定义:minor GC是清理年轻代,Major GC是清理年老代,Full GC是清理整个堆空间。