一、MarkSweep 标记清除算法
分为两个阶段:标记阶段、清除阶段
标记阶段:将可清理可回收的对象内存块标记出来
清楚阶段:直接讲垃圾内存回收
缺点:会产生大量的内存碎片
二、Copying拷贝算法
为了解决标记清除算法产生的内存碎片问题,产生的算法
原理:将内存分为大小相等的两块,每次只使用其中一块.垃圾回收时,将当前这一块内存中村回的对象全部copy到另一半中.然后,当前这一半内存就可以直接清理
优点:不会产生内存碎片
缺点:浪费内存空间,且会出现效率问题(可用对象越多,那么会提高对可用对象的操作频率,促使性能下降),存活对象移动次数太多
三、MarkCompack标记压缩算法
为了解决Copying算法的缺陷, 产生了标记压缩算法.标记阶段与标记清除算法一致.但是在完成标记猴后会将存活对象往一端移动.然后将端边界以外的所有内存,直接清除
三种算法,各有利弊,有各自的适用场景
四、什么是STW
STW(Stop-the-World)是指垃圾回收器暂停整个应用程序的运行,将JVM内存冻结的一种状态,以便在内存管理系统中执行清理和维护。JAVA所有线程都停止执行,GC线程除外,native方法可以执行,但是不能与JVM交互.GC算法优化的重点就是减少STW,同时也是JVM调优的重点
五、垃圾回收器
垃圾回收器大致分为两类:分代算法回收器、不分代算法回收器
分代算法:
新生代:Serial、ParNew、ParallelScavenge
老年代:CMS、SerialOld、ParallelOld
配合关系:
Serial- >SerialOld.
CMS->ParNew
ParallelScavenge->ParallelOld
不分代算法:
Epsilon、Shennandoah、G1、ZGC
Serial->SerialOld:
串行回收机制,需要GC时,直接STW,GC完了再继续.早期垃圾回收器,只有一个线程执行GC.在多CPU架构下,性能下降严重,只适合几十M的内存空间使用.
ParallelScavenge->ParallelOld:
在串行的基础上,增加GC线程.PS+PO这种组合是JDK1.8默认的垃圾回收器.在多CPU架构下,大大提升了GC性能
CMS->ParNew:
分为四个阶段:
初始标记:(STW)标记出根对象直接引用的对象.
并发标记:从根对象继续查找其他的对象,与应用程序是并发执行.
重新标记:(STW)对并发执行阶段的对象进行重新标记
并发清除:并行将产生的垃圾清楚.清除过程中,应用程序又会不断的产生新的垃圾,叫做浮动垃圾.这些垃圾要到下一次GC过程中清除
核心算法:三色标记
可以用于并发标记算法和非并发标记算法。该算法将所有对象分成三个颜色:白色、灰色和黑色。
白色:从未被扫描过的对象,即它们的可达性还没有被决定
灰色:已被扫描过,但其引用还没有全部扫描过的对象。
黑色:已扫描了所有引用的对象。
程序运行,内存发生变化,可能会存在漏标的场景.cms的解决办法是增量标记
Shennandoah:
Shenandoah是一种低延迟的垃圾回收器,由Red Hat公司开发。是并发GC算法,减少GC的STW。提供了很高的吞吐量和低的全局暂停时间。它采用多线程、可停止的并发标记周期和并发处理对象复制算法。该算法基于C2 JIT编译器并与JVM的内部调度和内存管理子系统紧密集成。Shenandoah GC的最大优势是在多核和大内存系统上工作时性能稳定,因为它能够扩展到处理器数量和内存大小上的增长。它适用于大型企业级Java应用程序,可以复制数十GB甚至上百GB的堆,并扩展到数百个处理器。主要是OpenJDK在使用,从JDK 12版本开始,Shenandoah在Hotspot中被作为实验性特性引入
注意:在应用Shenandoah之前,需要对应用程序的性能、内存使用方式以及GC的行为有充分的了解和评估。此外,Shenandoah并不适用于所有的应用场景,因为它可能会带来一些额外的开销和性能问题。因此,开发人员应该仔细评估Shenandoah的优势和劣势,了解它适用的场景,并根据自己的实际需求进行选择。
初始标记阶段:(STW)标记所有的根引用。
并发标记阶段:(类似CMS的并发标记)执行跨代(包括老年代和年轻代)的标记操作。会创建一个只读快照,确保在标记过程中新分配的对象不会被遗漏
(没太懂下划线这句的意思,查了一下资料.备注一下:
在Shenandoah的并发标记阶段中,由于应用程序可能会在标记过程中不断创建新的对象,垃圾收集器需要确保这些新对象不会被遗漏,否则就会出现内存泄漏问题。
为了解决这个问题,Shenandoah会在并发标记阶段开始时创建一个只读快照。具体而言,它会扫描整个堆,将所有已有的对象标记为“存活”,并在快照中记录下来。之后,垃圾收集器会使用该快照作为标记对象的参考,以确保新对象被正确跟踪
在并发标记阶段中,垃圾收集器会扫描根的引用,将其标记为“活着”并进行追踪,直到它达到了堆上的所有对象。在此过程中,如果遇到一个新对象,则会将其与快照进行比较,从而确定该对象是否需要被跟踪。
需要注意的是,在并发标记过程中,由于应用程序可能在垃圾收集器执行的同时修改了对象,因此垃圾收集器需要对被修改的对象进行特殊处理,以确保将它们标记为“存活”并正确追踪之。Shenandoah会使用“取样式写屏障”技术来防止这种情况发生,该技术允许Shenandoah在并发标记期间看到所有已修改的对象并对其进行标记。
总之,Shenandoah将只读快照用于标记过程,以确保不遗漏新创建的对象。此外,在并发的标记阶段中,垃圾收集器会使用一系列技巧来处理应用程序对内存中对象的并发修改,以确保所有对象都被正确标记并跟踪。
还是没太懂,后续查到相关资料理解了之后再重新修改补充一下这块)
并发追踪阶段:快速遍历可能会被修改的对象,并将这些对象标记为“仍在使用”。并发追踪阶段使用的是灰度追踪算法,该算法可以在与应用程序并发运行的情况下处理大型堆。
最终标记阶段:(STW)在此阶段中,Shenandoah会在标记根集之后重新扫描所有被访问的对象并且标记为可回收对象,确保不会误判。
并发清除阶段:在此阶段中,Shenandoah会将所有不可达对象从堆中清除。删除被标记为不可达的对象时,虚拟机使用了一个解决“重访”问题的技巧。收集器将堆划分成多个区域,每个区域的清理都在不同的时间进行,垃圾收集器会在并发时从一个区域切换到另一个区域。
G1: GarbageFirst 垃圾优先
内存模型是实际部分带,但逻辑上是分代的.在内存模型中,对于堆内存就不再分老年代和新生代,而是划分成一个个的小内存块,叫Region.每个Region可以隶属于不同的代
初始阶段:(STW)标记出GCRoot直接引用的对象.
标记Region:通过RSet标记出上一个阶段标记的Region引用到Old区的Region
并发标记阶段:(类似CMS)但是,遍历的范围不再是整个Old区.而只需要遍历第二步标记出来的Region.
重新标记:(STW)类似CMS
垃圾清理:G1可以采用Copying算法.直接将整个Regin中的对象copy到另一个Region.G1只选择垃圾较多的Region来清理,并不是完全清理
ZGC:
ZGC是从JDK 11开始推出的,因此它适用于所有基于JDK 11或更高版本的JVM。可以通过使用命令行选项
-XX:+UseZGC
来启用ZGC垃圾回收器。同时,ZGC目前仅适用于Linux/x64平台,是JDK 11+版本的默认垃圾回收器。如果你需要在使用其它操作系统或处理器架构上使用ZGC,则需要安装Oracle JDK 11或更高版本。
注意:Java 11的ZGC作为实验特性(Experimental Feature)引入,但在Java 15中已经被高度成熟并且是稳定的默认垃圾回收器,并且一般来说,使用ZGC对于生产环境来说是非常稳定和可行的。该垃圾回收器已经被广泛应用于高并发、大内存的Java应用程序,包括金融、电商、游戏等行业。
预处理:在ZGC启动时,它会为堆中所有对象建立一个初始的分代,即一个内存区域列表。ZGC使用分代来更好地管理对象的生命周期,减少收集时间。它还会在预处理阶段中扫描堆以建立一个快照,并构建一张有向可达性图(Directed Acyclic Graph,DAG),用于标识当前存活对象之间的引用关系
并发标记阶段:一旦ZGC开始运行,即使应用程序正常运行,ZGC也会尝试标记所有活动对象。它使用许多线程来遍历存活对象,同时记录对象的状态和堆中引用的位置。在遍历阶段,如果堆中引用对象的指针发生更改,ZGC会使用读入屏障来确保新的引用值是准确、一致的。
并发重定向阶段:(STW)内存中所有标记为垃圾对象的区域都会被回收。会执行一次重定向(Relocation)阶段,这个阶段可以将存活对象移动到新的内存位置上,从而释放原有的空间,这个阶段也是并发执行的。在重定向阶段中,ZGC将识别并标记活动对象的引用关系,如果一个对象需要在内存中移动,则会在新位置分配内存空间,并将旧地唯一的空间指针更新为新地址。
并发清除阶段:回收那些不再需要的对象。将不需要的对象从数据结构中删除,并从后台线程中删除它们。 ZGC会从所有堆中的区域中从中找到可以回收的区域,并将其在管理上标记为“空白”。空白区域将被用于下一次内存分配,以便更快地进行内存分配。这个阶段是并发地执行的,不会影响Java应用程序的性能。
重点:ZGC中只有并发重定向阶段(Concurrent Re-Mapping)阶段需要STW。在并发重定向触发时,Java应用程序需要暂停一小段时间,以等待GC完成对象的移动和地址重定向。但这个阶段的暂停时间非常短,往往不会超过10ms(取决于内存大小),而且只会发生几次。其他几个GC阶段均是并发执行的,不需要stw,不会影响Java应用程序的性能和响应性能。因此,ZGC是一种非常适合高并发、大内存的应用程序的垃圾回收器
以上内容是通过所学课程与查询相关资料整理出来的.如有问题或什么的,评论或私信,我进行相关修改