一 垃圾回收器
之前说了jvm运行时会进行垃圾回收,然后他会通过算法来进行处理回收,算法算是底层的实现,在算法之上还要有包含他的容器,它包含了算法以及其他要做的事,这种东西就是垃圾回收器。
垃圾回收器有好几种,随着时间的迭代,后期研发出来的垃圾回收器变得越来越强大,但不是说前面的垃圾回收器就会被淘汰,因为如果杀鸡用牛刀,反而增加了维护的成本,下面就来一一介绍他们。
1 Serial收集器
这玩意是长老集的垃圾回收器,他是单线程的,他进行垃圾回收的时候其他线程一定就要停止工作,Stop the world,造成很长时间的停顿,但是他也有用武之地,对于一些桌面应用程序,比较多的使用单线程,本身占用内存很小,那么就不会经常进行垃圾回收,所以他对于Client模式的虚拟机来说是一个不错的选择
2 ParNew收集器
他是Serial收集器的多线程版本,解决了Serial的单线程慢的问题。他是并行的。
3 Parrallel Scavenge收集器
他是一个新生代收集器,使用复制算法,是一个并发收集器,主要关注点是提高吞吐量,而CMS的关注点是减少停顿时间
4 Serial Old收集器
他是Serial收集器的老年代版本,使用标记整理算法,也是主要用为Client客户端
5 Parrallel Old收集器
他是Parrallel Scavenge收集器的老年代版本,使用标记-整理算法。
6 CMS收集器
这款收集器应该说是现在应用最广泛的收集器,他使用标记-清除算法,他的工作流程是
1)初始标记
2)并发标记
3)重新标记
4)并发清除
初始标记就是标记对象的GC-Root,并发标记就是对之前标记的GC-ROOT进行一个追踪,因为对象是动态的,重新标记就是因为并发标记可能存在漏标,所以他是进行一次修正,并发清楚就是发现对象没被使用就可以清楚掉了。
这其中初始标记和重新标记都是要Stop the World的,但是最大工作量的并发标记和并发清楚却不需要停顿,这样就有效了减少了GC的停顿时间。但是即便如此,他也不是完美的,他也有他的缺点。第一点就是他是基于标记-清除算法的,这就意味着他也会产生不连续的空间碎片,导致大对象无法分配连续空间从而GC
第二点就是他对CPU资源很敏感,因为他是多线程,多线程就会占用CPU的资源,最终可能造成系统的吞吐量下降
第三点就是他无法清楚浮动垃圾,他清理的过程中产生的新垃圾CMS是无法清理的,所以他要留一部分内存给浮动垃圾jdk1.5是只要垃圾占用68%就会触发老年代GC,1.6jdk时提升到了92%
7 G1收集器
他是最新的垃圾回收器,他的目的是未来替换掉JDK1.5发布的CMS垃圾回收器。G1整体上是通过标记-整理算法来实现,局部是使用复制算法来实现,并且他有可预测停顿时间的功能
他和其他的垃圾回收器的区别是他既能回收新生代,也能回收老年代,而其他的垃圾回收器都只能回收新生代或者老年代一个区域
他是把堆内存分成若干个region,不像其他的回收器,将新生代与老年代进行物理隔离,g1仍然保留新生代和老年代的概念。
另外由于有可预测停顿时间的模型,在g1进行回收的时候,就可以根据时间来选择回收不同大小的region,增加效率
他的流程是初始标记->并发标记->最终标记->筛选回收
二 线上GC日志分析
程序是如果进行GC的,如果我们需要查看具体的内容就要查看运行时程序对Gc的记录日志,这部分就是GC日志
我们先来看一段线上GC日志
1 新生代日志
2021-03-13T22:58:49.129+0800: 4.268: [GC2021-03-13T22:58:49.129+0800: 4.268: [ParNew: 545344K->68095K(613440K), 0.0885980 secs] 545344K->83421K(2029056K), 0.0886940 secs] [Times: user=0.24 sys=0.02, real=0.09 secs]
里面的ParNew代表的就是使用新生代垃圾回收器ParNew,这个回收器上面有提过,545344K->68095K(613440K)表示回收前占用空间是545344K,回收后占用空间是68095K,后面括号里面的613440K代表新生代总容量,后面的545344K->83421K(2029056K),堆内存回收前为545344K回收后为83421K,后面括号里面的2029056K代表老年代代总容量。而他们后面的secs为耗时的秒数。
2 老年代日志
2021-03-16T00:42:12.840+0800: 179007.980: [Full GC2021-03-16T00:42:12.840+0800: 179007.980: [CMS: 282565K->193453K(1415616K), 1.0402280 secs] 559324K->193453K(2029056K), [CMS Perm : 149075K->147987K(149484K)], 1.0406820 secs] [Times: user=1.04 sys=0.00, real=1.04 secs]
上面那段是新生代的GC回收日志,这段是老年代的回收日志,我们可以明显的看到了Full GC,也看到了CMS,也就是证明了老年代使用了CMS垃圾回收器,后面还有一个Perm,他的意思是回收区域为老年代,后面的[Times: user=1.04 sys=0.00, real=1.04 secs]user为用户消耗的cpu时间,sys为内核态消耗时间,以及从开始到结束的墙钟时间,我们关注最好一个就好。
3 GC日志展示的jvm参数
CommandLine flags: -XX:ConcGCThreads=4 -XX:GCLogFileSize=10485760 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/applog -XX:InitialHeapSize=2147483648 -XX:MaxHeapSize=7784628224 -XX:MaxNewSize=697933824 -XX:MaxPermSize=536870912 -XX:MaxTenuringThreshold=6 -XX:NumberOfGCLogFiles=10 -XX:OldPLABSize=16 -XX:ParallelGCThreads=8 -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseGCLogFileRotation -XX:+UseParNewGC
网友评论