JVM-6-垃圾回收算法

三如何垃圾回收
 
GC(Garbage Collection)垃圾回收算法

 

  • 标记清除    速度快,但是会产生内存碎片;
  • 标记整理    解决了标记清除内存碎片的问题,但是每次都得移动对象,因此成本很高;
  • 复制算法    没有内存碎片也不需要移动对象,但是导致空间的浪费

        分代收集算法:在上边三种收集思想中加入了分代的思想。

 
 

标记清除(Mark-Sweep)

这种算法分两步:标记、清除两个阶段。
 
标记阶段是从根集合(GC Root)开始扫描,每到达一个对象就会标记该对象为存活状态,
清除阶段在扫描完成之后将没有标记的对象给清除掉。
 
这个算法有个缺陷就是会产生内存碎片,如上图B被清除掉后会留下一块内存区域,如果后面需要分配大的对象就会导致没有连续的内存可供使用。
 
 

标记整理(Mark-Compact)

 
标记整理就没有内存碎片的问题了,也是从根集合(GC Root)开始扫描进行标记然后清除无用的对象,清除完成后它会整理内存。
 
这样内存就是连续的了,但是产生的另外一个问题是:每次都得移动对象,因此成本很高。
 
 

复制算法(Copying) 

 
复制算法会将JVM推分成二等分,如果堆设置的是1g,那使用复制算法的时候堆就会有被划分为两块区域各512m。给对象分配内存的时候总是使用其中的一块来分配,分配满了以后,GC就会进行标记,然后将存活的对象移动到另外一块空白的区域,然后清除掉所有没有存活的对象,这样重复的处理,始终就会有一块空白的区域没有被合理的利用到。
两块区域交替使用,最大问题就是会导致空间的浪费,现在堆内存的使用率只有50%。
 

 

 

 
分代收集法
 
目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存
划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young
Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃
圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法
 
 
 在新生代-复制算法
每次垃圾收集都能发现大批对象已死, 只有少量存活. 因此选用复制算法, 只需要付出少量
存活对象的复制成本就可以完成收集.
 
在老年代-标记整理算法
因为对象存活率高、没有额外空间对它进行分配担保, 就必须采用“标记—清理”或“标
记—整理”算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存.
 
 
 
分区收集算法
 
分区算法则将整个堆空间划分为连续的不同小区间, 每个小区间独立使用, 独立回收. 这样做的
好处是可以控制一次回收多少个小区间 , 根据目标停顿时间, 每次合理地回收若干个小区间(而不是
整个堆), 从而减少一次 GC 所产生的停顿
 
java 虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器
 
                                
新生代的垃圾收集器主要有:
  • Serial收集器: Serial收集器是在client模式下默认的新生代收集器,其收集效率大约是100M左右的内存需要几十到100多毫秒;在client模式下,收集桌面应用的内存垃圾,基本上不影响用户体验。所以,一般的Java桌面应用中,直接使用Serial收集器(不需要配置参数,用默认即可)。
  • ParNew收集器:Serial收集器的多线程版本,这种收集器默认开通的线程数与CPU数量相同,-XX:ParallelGCThreads可以用来设置开通的线程数。 可以与CMS收集器配合使用,事实上用-XX:+UseConcMarkSweepGC选择使用CMS收集器时,默认使用的就是ParNew收集器,所以不需要额外设置-XX:+UseParNewGC,设置了也不会冲突,因为会将ParNew+Serial Old作为一个备选方案; 如果单独使用-XX:+UseParNewGC参数,则选择的是ParNew+Serial Old收集器组合收集器。 一般情况下,在server模式下,如果选择CMS收集器,则优先选择ParNew收集器。
  • Parallel Scavenge收集器:关注的是吞吐量(关于吞吐量的含义见上一篇博客),可以这么理解,关注吞吐量,意味着强调任务更快的完成,而如CMS等关注停顿时间短的收集器,强调的是用户交互体验。 在需要关注吞吐量的场合,比如数据运算服务器等,就可以使用Parallel Scavenge收集器。
 
对象如果在年轻代存活了足够长的时间而没有被清理掉(即在几次Young GC后存活了下来),则会被复制到年老代,年老代的空间一般比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。当年老代内存不足时,将执行Major GC,也叫 Full GC。
年老代的垃圾收集器有:
  • Serial Old收集器:在1.5版本及以前可以与 Parallel Scavenge结合使用(事实上,也是当时Parallel Scavenge唯一能用的版本),另外就是在使用CMS收集器时的备用方案,发生 Concurrent Mode Failure时使用,如果是单独使用,Serial Old一般用在client模式中。
  • Parallel Old收集器:在1.6版本之后,与 Parallel Scavenge结合使用,以更好的贯彻吞吐量优先的思想,如果是关注吞吐量的服务器,建议使用Parallel Scavenge + Parallel Old 收集器。
  • CMS收集器:这是当前阶段使用很广的一种收集器,国内很多大的互联网公司线上服务器都使用这种垃圾收集器,CMS收集器以获取最短回收停顿时间为目标,非常适合对用户响应比较高的B/S架构服务器。
  • CMSIncrementalMode: CMS收集器变种,属增量式垃圾收集器,在并发标记和并发清理时交替运行垃圾收集器和用户线程。
  • G1 收集器:面向服务器端应用的垃圾收集器,计划未来替代CMS收集器。
 
 
 
 

 

 
posted @ 2019-12-01 14:05  wf.zhang  阅读(153)  评论(0编辑  收藏  举报