jvm诊断与优化(6)

    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)

jvm诊断与优化(6)_第1张图片
   
多线程,非独占。这个是在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这个任务


你可能感兴趣的:(jvm诊断与优化(6))