垃圾回收算法你不知道的奥秘

程序员小迷 2024-05-03 12:58:57

一、对象回收判定方法

1.引用计数法(PHP语言在用):快,方便,实现简单,缺点:对象相互引用时,很难判断对象是否该回收。

2.可达性分析(Java语言在用)

通过一系列的称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,可以被回收。

能作为GC Roots的对象包括下面几种:

1) 方法区中常量引用的对象。

2) 方法区中类静态属性引用的对象。

3) 虚拟机栈(栈帧中的本地变量表)中引用的对象。

4) 本地方法栈中JNI(即Native方法)引用的对象。

二、垃圾回收算法分类

1.Serial/Serial Old

最古老的,单线程,独占式,成熟,适合单CPU 服务器。

2.ParNew

和Serial基本没区别,唯一的区别:多线程,多CPU的,停顿时间比Serial少。

ParNew垃圾收集器是Serial收集器的多线程版本。

3.Parallel Scavenge

吞吐量优先收集器。 新生代,复制算法。 并行的多线程收集器。 类似ParNew,更加关注吞吐量,达到一个可控制的吞吐量。 Server级别多CPU机器上的默认GC方式,主要适合后台运算不需要太多交互的任务。

4.Parallel Old

老年代,标记整理算法。 并行的多线程收集器。

是Parallel Scavenge收集器的老年代版本,为了配合Parallel Scavenge的面向吞吐量的特性而开发的对应组合。

在注重吞吐量以及CPU资源敏感的场合采用 。

5.CMS

用于老年代,标记清除算法。 并行与并发收集器。

尽可能的缩短垃圾收集时用户线程停止时间。缺点在于:

1)内存碎片 。

2)需要更多cpu资源 。

3)浮动垃圾问题,需要更大的堆空间 。 用于重视服务的响应速度、系统停顿时间和用户体验的互联网网站或者B/S系统。互联网后端目前CMS是主流的垃圾回收器。

6.G1

跨新生代和老年代。标记整理 + 化整为零 。 并行与并发收集器 。 JDK1.7才正式引入,采用分区回收的思维,基本不牺牲吞吐量的前提下完成低停顿的内存回收。可预测的停顿是其最大的优势。 面向服务端应用的垃圾回收器,目标为取代CMS。

并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop The World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。

分代收集:与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。

空间整合:与CMS的"标记—清理"算法不同,G1从整体来看是基于"标记—整理"算法实现的收集器,从局部(两个Region之间)上来看是基于"复制"算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。

内存布局:在G1之前的其他收集器进行收集的范围都是整个新生代或者老年代,而G1不再是这样。使用G1收集器时,Java堆的内存布局就与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。

1) 新生代GC

回收Eden区和Survivor区,回收后,所有Eden区被清空,存在一个Survivor区保存了部分数据。老年代区域会增多,因为部分新生代的对象会晋升到老年代。

2) 并发标记周期

初始标记:短暂,仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,产生一个全局停顿,都伴随有一次新生代的GC。

根区域扫描:扫描Survivor区可以直接到达的老年代区域。

并发标记阶段:扫描和查找整个堆的存活对象,并标记。

重新标记:会产生全局停顿,对并发标记阶段的结果进行修正。

独占清理:会产生全局停顿,对GC回收比例进行排序,供混合收集阶段使用。

并发清理:识别并清理完全空闲的区域,并发进行。

3) 混合收集

对含有垃圾比例较高的Region进行回收。

G1当出现内存不足的的情况,也可能进行的Full GC回收。

G1中重要的参数:

-XX:MaxGCPauseMillis 指定目标的最大停顿时间,G1尝试调整新生代和老年代的比例,堆大小,晋升年龄来达到这个目标时间。

-XX:ParallelGCThreads:设置GC的工作线程数量。

7.未来的垃圾回收器ZGC(Z Garbage Collector)

ZGC通过技术手段把stw(Stop The World)的情况控制在仅有一次,就是第一次的初始标记才会发生,这样也就不难理解为什么GC停顿时间不随着堆增大而上升了,再大也是通过并发的时间去回收了。

关键技术:

1) 有色指针(Colored Pointers)

2) 加载屏障(Load Barrier)

存储在对象字段中的对象引用被实现为有色指针。存储在 JVM 堆栈中的对象引用在硬件堆栈或 CPU 寄存器中实现为无色指针。读屏障和存储屏障控制有色指针和无色指针之间的转换。

三、垃圾回收算法配置

-XX:+UseSerialGC 新生代和老年代都用串行收集器。

-XX:+UseParNewGC 新生代使用ParNew,老年代使用Serial Old。

-XX:+UseParallelGC 新生代使用Paraller Scavenge GC,老年代使用Serial Old。

-XX:+UseConcMarkSweepGC  新生代使用ParNew,老年代的用CMS。

-XX:+UseG1GC 使用G1垃圾回收算法。

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是程序员小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

欢迎关注。助您在编程路上越走越好!

0 阅读:7