1、Serial(串行)收集器(新生代都采用复制算法)
这是个单线程的收集器:即 当他工作的时候,会停掉虚拟机所有的线程!(Stop The World)
2、ParNew(并行)收集器(新生代都采用复制算法)
这是Serial的升级版,允许多条GC线程同时回收,但是,依然要停掉所有的用户线程(Stop The World)
3、Parallel Scavenge收集器(新生代都采用复制算法):尽可能的减少用户程序的停顿时间
这也是并行收集器,跟ParNew看上去一样,但多了个重要的性能:可控吞吐量
吞吐量:运行用户代码时间/(运行用户代码时间+垃圾回收时间)
-XX:MaxGCPauseMillis=m:m是一个大于0的毫秒数。即:收集器尽可能的保证内存回收花费的时间不超过设定值。
-XX:GCTimeRatio=n:n是大于0小于100的整数。公式1/(1+n)为垃圾收集时间占总时间的百分比。即:如果n=9。那么1/(1+9)=10%。GC运行的时间占总时间的10%。
-XX:+UseAdaptiveSizePolicy:这是一个开关参数,打开这个参数之后,就不需要手动指定新生代的大小(-Xmn),Eden和Survivor的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,自动调整这些参数,以配合停顿时间或者吞吐量。
4、Serial Old收集器
是Serial的老年代收集器,老年代采用“标记-整理”算法。
5、Parallel Old 收集器
是Parallel Scavenge的老年代收集器,老年代采用“标记-整理”算法。
6、CMS 收集器 (Concurrent Mark Sweep)
获取最短回收停顿时间为目的。
整个过程:
1.初始标记(CMS initial mark):stop the world,时间短。串行
2.并发标记(CMS concurrent mark): 并发
3.重新标记(CMS remark):stop the world ,时间比初始标记长,但也很短。并行
4.并发清除(CMS concurrent sweep): 并发
说明:
1、CMS默认启动的回收线程:(CPU数量+3)/ 4。可以计算,cup数量不合适的时候,会占很多的cup。
2、浮动垃圾(Floating Garbage):CMS并发回收的同时,用户线程还在不断的产生垃圾,这部分垃圾只有在下次才会被回收。
3、JDK1.5默认当老年代使用到了68%时触发。调整参数:-XX:CMSInitiatingOccupancyFraction=70。即:老年代占70%的时候触发垃圾回收。。JDK1.6已经提升到92%
4、标记-清除 算法本身会有很多的内存碎片产生。所以有一下两个参数
-XX:+UseCMSCompactAtFullCollection :开关参数,默认开启。在老年代内存不够时,或者零碎内存放不下大对象时,进行内存压缩。
-XX:CMSFullGCsBeforeCompaction=5: 设置当进行5次不压缩的GC后,跟着来一次压缩的GC。
7、G1 收集器 (Garbage-First)
JDK7u4中开始应用,被赋予使命:替换CMS收集器。
整个过程:
1.初始标记(Initial marking):stop the world,时间短。串行
2.并发标记(Concurrent marking): 并发
3.最终标记(Final Marking):stop the world 。并行
4.筛选回收(Live Data Counting and Evacuation):stop the world 。并行
特点:
1、并发与并行。
2、分代收集(他可以不依赖分代)。
3、空间整合:整体采用“标记-整理”,局部(Region之间)采用“复制算法”。
4、可预测的停顿:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾回收上的时间不得超过N毫秒。
看起来没那么厉害,那他到底哪里好了?
实现:
1、“化整为零”,将整个堆区分为若干个Region(区域)。新生代和老年代不再物理隔离,而是各*不同的Region组成。
2、 价值大小:回收所获得的空间大小以及回收所需时间的经验值。在后台维护一个优先列表,每次根据允许的收集时间,有限回收加值大的Region。这种分区和优先级的模式,可以最大的保证在有限的时间内获取尽可能高的收集效率。
3、Remembered Set:为了避免或者尽可能减少由于Region之间对象的引用而引起的整个堆的扫描(因为Region之间可以互相引用,导致扫描不可能只发生在单个Region)。G1中每个Region都有与之对应的Remembered Set,虚拟机发现程序在对Reference类型进行写操作时(Reference写操作:就是将对象的引用关系写入Reference中),会产生一个Write Barrier暂时中断写操作,检查Reference类型是否在不同的Region,如果是,便通过CardTable吧相关的引用信息写入到被引用对象所属的Region中的Remembered Set中,保证不对全内存扫描,也不会遗漏内存垃圾。