JVM-6-垃圾回收算法
阅读原文时间:2023年10月01日阅读:1

三如何垃圾回收

GC(Garbage Collection)垃圾回收算法

  • 标记清除    速度快,但是会产生内存碎片;

  • 标记整理    解决了标记清除内存碎片的问题,但是每次都得移动对象,因此成本很高;

  • 复制算法    没有内存碎片也不需要移动对象,但是导致空间的浪费

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

标记清除(Mark-Sweep)

这种算法分两步:标记、清除两个阶段。

标记阶段是从根集合(GC Root)开始扫描,每到达一个对象就会标记该对象为存活状态,

清除阶段在扫描完成之后将没有标记的对象给清除掉。

.png)

这个算法有个缺陷就是会产生内存碎片,如上图B被清除掉后会留下一块内存区域,如果后面需要分配大的对象就会导致没有连续的内存可供使用。

标记整理(Mark-Compact)

标记整理就没有内存碎片的问题了,也是从根集合(GC Root)开始扫描进行标记然后清除无用的对象,清除完成后它会整理内存。

.png)

这样内存就是连续的了,但是产生的另外一个问题是:每次都得移动对象,因此成本很高。

复制算法(Copying)

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

.png)

两块区域交替使用,最大问题就是会导致空间的浪费,现在堆内存的使用率只有50%。

分代收集法

目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存

划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young

Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃

圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法

 在新生代-复制算法

每次垃圾收集都能发现大批对象已死, 只有少量存活. 因此选用复制算法, 只需要付出少量

存活对象的复制成本就可以完成收集.

在老年代-标记整理算法

因为对象存活率高、没有额外空间对它进行分配担保, 就必须采用“标记—清理”或“标

记—整理”算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存.

分区收集算法

分区算法则将整个堆空间划分为连续的不同小区间, 每个小区间独立使用, 独立回收. 这样做的

好处是可以控制一次回收多少个小区间 , 根据目标停顿时间, 每次合理地回收若干个小区间(而不是

整个堆), 从而减少一次 GC 所产生的停顿

java 虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器

                                .png)

新生代的垃圾收集器主要有:

  • 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收集器。

热门专题

smartgit过期

RequestPram 前端js提交

链路聚合ensp手工模式

Python为什么安装不了pyautogui

django中input怎么打开本地文件夹

linux 的环境变量区分大小写吗

Ubuntu 18.04 磁盘根目录在线扩容 & 修改分区

算法第4版pdf下载

swagger3.0.3分页

cnn和mlp执行时间

js的number类型的字边量来调用toString

bus lock错误

bootstrap django模态框

echarts 饼图不要鼠标经过

mybatis 获取 connection

xftp7要继续使用此程序,您必须使用最新的

java selenium切换标签页

所有早期版本的windows都不识别GPT分区形式

confluence8破解

Wob jdata的用途