STW(stop-the-world):当GC触发时为了正常且高效的执行,大部分情况下,会要求系统进入一个停顿的状态(终止所有的应用线程),保证应用不再产生新的垃圾及在某一瞬间的一致性,也更好的标记对象。所以这时应用程序将没有任何的响应,这个停顿叫STW。合理的配置堆与选择GC是优化的关键。
新生代GC-------------------------------------------------------------
1.串行回收器
单线程,独占式。单线程进行垃圾回收,每次回收只有一个线程在工作。它是最古老的一种当,jvm在client模式下它是默认的GC,因为古董所以成熟,它使用复制算法,实现相对简单、逻辑处理特别高效、且没有线程切换的开销。所以在单核cpu是不错的选择,特点:
①仅仅使用单线程
②独占式的(回收过程中,应用程序全部暂停直到回收结束)
-XX:+UseSerialGC //新生代与老年代都使用串行回收器
2.ParNew
多线程,独占式。在多核cpu情况下停顿时间要短于串行GC,但在单核情况下可能还不如串行GC
--XX:+UseParNewGc //新生代使用ParNew; 老年代使用串行GC
--XX:+UseConcMarkSweepGC //新生代使用ParNew; 老年代使用CMS
--XX:ParallelGcThreads //ParNew 使用的线程数量
参数说明:一般与cpu数量相当,当cpu数量大于8个时个数=3+((5*cpu个数)/8)
3.ParallelGC
多线程,独占式。与ParNew不同的是它非常关注系统的吞吐量(垃圾回收时间越少吞吐量就越高)
-XX:+UserParallelGc //新生代使用ParalleGC; 老年代使用串行GC
-XX:+UserParallelOldGC //新生代使用ParalleGC; 老年代使用ParalleOldGC
-XX:MaxGCPauseMillis //垃圾回收停顿时间,一个大于0的整数
参数说明:jvm会尽可能的把停顿时间调整到你所设的值之间,如果值很小势必导致回收次数增多,降低了吞 吐量
-XX:GCTimeRatio //吞吐最的大小;一个0~100的整数,默认19
参数说明:如取值99,则系统用于垃圾收集时间不超过1/(1+99)=1%,如果值很大那么停顿时间就会变长。
-XX:+UseAdaptiveSizePolicy //自动调整新生代空间大小,eden/survivor比例、晋升老年代的年龄参 数等,达到堆大小、吞吐量和停顿时间之间的平衡点。而你只要设置
MaxGcPauseMillis与GCTimeRatio就行
老年代GC---------------------------------------------------
1.串行回收器
单线程,独占式。与新生代中差不多,使用标记压缩算法。老年代的GC使用时间比新生代都要来行久(因为空间比较大,且算法的原故),所以在老年代串行GC它的停顿会久,它可以与很多新生代GC一起配置使用,也可以作为CMS 的的备用GC。
-XX:+UseSerialGC //新生代与老年代都使用串行回收器
-XX:+UseParNewGC //新生代使用ParNew ; 老年代使用串行
-XX:+UseParallelGc //新生代使用ParallelGC ; 老年代使用串行
2ParallelOld
多线程,独占式。它也是关注吞吐量的,与新生代中ParallelGC配合使用
-XX:+UseParallelOldGC //新生代使用ParallelGC; 老年代使用ParalleOld
-XX:ParallelGCThreads //设置垃圾回收时线程数量
3.CMS(Concurrent Mark Sweep 并发标记清除)
多线程,非独占。与ParallelOld不同,它关注的是系统停顿时间,使用标记清除算法。非独占是从整体来说的,因为在回收阶段中还有一些是独占的,不能完全做到非独占。这样虽然CMS的非独占减少了停顿时间,但在cpu紧张时受到CMS线程的影响。应用系统的性能可能非常的糟糕。
因为非独占,CMS在回收过程中系统同时也会产生出新的垃圾。双重作用下系统内存会很紧张,所以CMS不会等到内存不足时才去工作,而是在老年代空间达到一定值(CMSInitiatingOccupancyFraction)时就去加收。如果回收过程中已经出现了内存不足了,此时CMS就会失败,转而使用备用GC(即老年代串行回收器)。这时应用程序完全中断直到GC结束,这样反而情形更坏了,所以设置CMSInitiatingOccupancyFraction变得很重要
-XX:+UseConcMarkSweepGC //新生代使用ParNew; 老年代使用CMS
-XX:ConcGCThread 或 -XX:ParallelCMSThreads //并发线程数量
参数说明:默认数量是(ParallelGCThreads+3)/4。
-XX:CMSInitiatingOccupancyFraction68 //指当老年代空间使用率达68%时执行一次CMS,默认68
-XX:+UseCMSCompactAtFullCollection //指当CMS后进行一次内存碎片整理
-XX:CMSFullGCsBeforeCompaction5 //指经过5次CMS后进行一次内存碎片整理
-XX:+CMSClassUnloadingEnabled //允许CMS回收Perm区的Class数据
-XX:CMSInitiatingPermOccupancyFraction60 //当永久区使用率达到60%时,Perm就进行回收
双工GC----------------------------------------------------------------------
1.G1(Garbage-First)
多线程,非独占。这个是在jdk1.7中正式使用的全新垃圾回收器,目标为了取代CMS。与之前的回收器截然不同因为它增加了分区算法,这样从结构上看它并不要求整个eden、年轻代、老年代都连续。但G1依然属于分代回收器,只是在逻辑上划分了。如上图
特点(主要于CMS进行比对):
①并行性:GC回收过程中多个线程同时工作
②并发性:G1部分工作与应用程序交替工作
③双工: 它同时兼顾年轻代与老年代。与上面的不同,它们或者工作在年轻代或者工作在老年代
④内存整理:在回收过程就进行对象的移动,不像CMS要特别进行一次碎片清理
⑤分区: 因为采用了分区,所以G1可以只选取部分区域进行回收,控制了一次回收内存大小。减少了停顿
与CMS一样当内存空间不足,jvm就会放弃G1转而使用Full GC,同样会出现应用程序的停顿。
-XX:+UseG1GC //使用G1回收器
-XX:MaxGCPauseMillis //指定目标最大停顿时间
参数说明:如果GC任何一次停顿超过这个值,G1就会尝试调整新生代和老年代的比例、调整堆的大小、调整晋升年龄,试图达到预设目标。如果该值偏小,对于新生代意味着增加GC的次数。对于老年代来说增加了Full GC的可能。
-XX:ParallelGCThreads //并行回收,GC的工作线程数量
-XX:InitiatingHeapOccupancyPercent45 //指定当整个堆使用率达到45%时执行并发标记
参数说明:一旦该值设定,始终都不会被G1修改,这意味着G1不会试图改变这个值,来满足MaxGCPauseMillis的目标,该值偏大会导致并发周期迟迟行不到启动,引起Full GC;如果该值偏小,会使得并发周期变得频繁,产生大量的GC线程最终将导致应用程序性能下降。
扩展点---------------------------------------------------------------------------
Full GC
这个并不是一个特别的垃圾回收器,指老年代的回收而应用程序将完全中断。同时串行与并行的Full GC是不一样,区别在于并行的FullGC 在回收老年代的同时,也会触发新生代的回收,而串行不会。如果不需要这个特性可以使用以下参数
-XX:-ScavengeFeforeFullGC //除去full gc 之前的那次新生代GC
System.gc()
在java中我们可以调用System.gc()去触发一次Full GC。而一般情况下我们认为回收动作是交给系统的,无需手动去触发,频繁触发对系统性能不好。而且使用System.gc(),在默认情况下是独占cpu(无论你是否使用并发GC),也就是说应用程序将中断运行,所以不建议使用。
-XX:+DisableExplicitGC //java 中禁用System.gc(),即使调用也视为一个空方法
-XX:+ExplicitGCInvokesConcurrent //调用System.gc()后让GC并发去回收垃圾
知识点--------------------------------------------
并发线程
并发也就是非独占的,指GC线程与应用线程进行交替执行
并行线程
一种任务下多个线程同时执行。如并行GC,指多个线程同时执行GC这个任务