几种垃圾收集器:
Serial收集器: 单线程的收集器,收集垃圾时,必须stop the world,使用复制算法。
ParNew收集器: Serial收集器的多线程版本,也需要stop the world,复制算法。
Parallel Scavenge收集器: 新生代收集器,复制算法的收集器,并发的多线程收集器,目标是达到一个可控的吞吐量。如果虚拟机总共运行100分钟,其中垃圾花掉1分钟,吞吐量就是99%。
Serial Old收集器: 是Serial收集器的老年代版本,单线程收集器,使用标记整理算法。
Parallel Old收集器: 是Parallel Scavenge收集器的老年代版本,使用多线程,标记-整理算法。
CMS(Concurrent Mark Sweep) 收集器: 是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重新标记,并发清除,收集结束会产生大量空间碎片。
G1收集器: 标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。不会产生空间碎片,可以精确地控制停顿。
目前线上情况:堆内存2G,年轻代768M,占37.5%;使用CMS作为老年代垃圾回收器,ParNew作为新生代垃圾回收器
/usr/local/matrix/bin/java -javaagent:/usr/local/dkimi-agent2/dkimi-core.jar=/usr/local/dkimi-agent2/config.properties -server -Xms2048m -Xmx2048m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m - -Dsun.net.inetaddr.ttl=1 -Dsun.net.inetaddr.negative.ttl=1 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/data0/www/logs/test-risk-portal/gc-%t.log -Djavax.net.debug=ssl -Xdebug -Xmn768m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseFastAccessorMethods -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSScavengeBeforeRemark -XX:+ExplicitGCInvokesConcurrent
一、各jdk版本默认垃圾收集器
jdk1.7和1.8默认垃圾收集器为-XX:+UseParallelGC:Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.9默认为G1收集器
二、垃圾回收算法
标记-清除:1、标记阶段:从GC Roots(栈和方法区里的对象:局部变量、常量等)开始,标记可达对象;2、清除阶段:清除不可达对象(会造成大量的空间碎片)
复制算法:将eden和幸存区可达对象,复制到另一个幸存区,然后清除eden和幸存区(适合年轻代,少量对象存活);
标记-整理:标记阶段也是从root开始标记可达;压缩阶段:将可达对象压缩至内存的一端,清理边界外的所有空间(适合老年代,存活对象较多)。
三、CMS和G1比较
1、初始标记:都暂停用户线程,标记和GC Roots直接关联的对象;
2、并发标记:都可以和用户线程并发执行,从GC Roots开始标记整个堆可达对象;
3、最终标记:都必须暂停用户线程,标记“并发标记”阶段有变化的部分对象;
4、回收:CMS和用户线程并发执行;G1默认暂停用户线程,G1内存是分成N个大小相等的Region,对各个Region的回收成本和价值进行排序,根据用户的期望时间来制定回收计划,回收部分Region。
四、垃圾收集器:
从串行到并行,再到部分阶段和用户线程并发执行,再分Region部分回收,减少用户线程的停顿时间。
可达性分析算法,可作GCRoot的对象:
(要回收的是堆中的对象,并且被其他区直接引用的的对象都可以作为GCRoot对象)
1、虚拟机栈(栈帧中的本地变量表)中的引用的对象。
2、本地方法栈中JNl(即一般说的Native方法)的引用的对象
3、方法区中的类静态属性引用的对象。(jdk1.8取消了方法区)
4、方法区中的常量引用的对象。(jdk1.8取消了方法区)
五、一次线上GC参数调优
从jdk7升到8,从垃圾收集器Parallel改为G1,其他参数不变的情况下,发生频繁的young gc,并且full gc也比之前更加频繁;
虽然每次gc时间不是很长,但gc的次数增到,导致一次请求过程可能碰上几次gc,造成一次请求耗时长;
业务特点:本地缓存了较多大对象数据,G1默认的Region大小为1M,对于大对象经常不够分配,导致频繁GC;于是将Region大小改为8M,之前young gc频繁问题解决;目前情况young gc10几分钟一次,full gc几乎没有: