写点什么

说一下 jvm 有哪些垃圾回收器?,kalilinux 渗透教程百度云

用户头像
极客good
关注
发布于: 刚刚

-XX:+UseSerialGC 开启串行垃圾回收器。


二、并行垃圾回收器




并行垃圾回收器是通过多线程进行垃圾收集的。也会暂停其它所有的工作线程(Stop The World,STW)。适合 Server 模式以及多 CPU 环境。一般会和 JDK1.5 之后出现的 CMS 搭配使用。并行的垃圾回收器有以下几种:


ParNew:Serial 收集器的多线程版本,默认开启的收集线程数和 CPU 数量一样,运行数量可以通过修改 ParallelGCThreads 设定。用于新生代手机,复制算法。用-XX:+UseParNewGC,和 Serial Old 收集器组合进行内存回收。


Parallel Scavenge: 关注吞吐量,吞吐量优先,吞吐量=代码运行时间/(代码运行时间+垃圾收集时间),也就是高效率利用 CPU 时间,尽快完成程序的运算任务可以升值最大停顿时间 MaxGCPauseMillis 以及,吞吐量大小 GCTimeRatio。如果设置了-XX:+UseAdaptiveSizePolicy 参数,则随着 GC,会动态调整新生代的大小,Eden,Survivor 比例等,以提供最合适的停顿时间或者最大的吞吐量。用于新生代收集,复制算法。通过-XX:+UseParallelGC 参数,Server 模式下默认提供了其和 SerialOld 进行搭配的分代收集方式。


Parllel Old:Parallel Scavenge 的老年代版本。JDK 1.6 开始提供的。在此之前 Parallel Scavenge 的地位也很尴尬,而有了 Parllel Old 之后,通过-XX:+UseParallelOldGC 参数使用 Parallel Scavenge + Parallel Old 器组合进行内存回收。


三、CMS 收集器




CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器。从名字就能知道它是标记-清除算法的。但是它比一般的标记-清除算法要复杂一些,分为以下 4 个阶段:


  1. 初始标记:标记一下 GC Roots 能直接关联到的对象,会"Stop The World"。

  2. 并发标记:GC Roots Tracing,可以和用户线程并发执行。

  3. 重新标记:标记期间产生的对象存活的再次判断,修正对这些对象的标记,执行时间相对并发标记短,会“Stop The World”。

  4. 并发清除:清除对象,可以和用户线程并发执行。


由于垃圾回收线程可以和用户线程同时运行,也就是说它是并发的,那么它会对 CPU 的资源非常敏感,CMS 默认启动的回收线程数是(CPU 数量+3)/ 4,当 CPU<4 个时,并发回收是垃圾收集线程就不会少于 25%,而且随着 CPU 减少而增加,这样会影响用户线程的执行。而且由于它是基于标记-清除算法的,那么就无法避免空间碎片的产生。CMS 收集器无法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而导致另一次 Full GC 的产生。


所谓浮动垃圾,在 CMS 并发清理阶段用户线程还在运行着,伴随程序运行自然还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS 无法在当次收集中处理掉它们,只能留待下一次 GC 时再清理掉。


四、G1 垃圾收集器



1、G1 垃圾收集器

把 G1 单独拿出来的原因是其比较复杂,在 JDK 1.7 确立是项目目标,在 JDK 7u2 版本之后发布,并在 JDK 9 中成为了默认的垃圾回收器。通过“-XX:+UseG1GC”启动参数即可指定使用 G1 GC。


G1 从整体看还是基于标记-清除算法的,但是局部上是基于复制算法的。这样就意味者它空间整合做的比较好,因为不会产生空间碎片。G1 还是并发与并行的,它能够充分利用多 CPU、多核的硬件环境来缩短“stop the world”的时间。G1 还是分代收集的,但是 G1 不再像上文所述的垃圾收集器,需要分代配合不同的垃圾收集器,因为 G1 中的垃圾收集区域是“分区”(Region)的。G1 的分代收集和以上垃圾收集器不同的就是除了有年轻代的 ygc,全堆扫描的 full?GC 外,还有包含所有年轻代以及部分老年代 Region 的 Mixed?GC。G1 还可预测停顿,通过调整参数,制定垃圾收集的最大停顿时间。


G1 收集器的运作大致可以分为以下步骤:初始标记、并发标记、最终标记、筛选回收。其中初始标记阶段仅仅只是标记一下 GC Roots 能直接关联到的对象,并且修改 TAMS(Next Top at Mark Set)的值,让下一个阶段用户程序并发运行时,能在正确可用的 Region 中创建新对象,这个阶段需要 STW,但耗时很短。并发标记阶段是从 GC Roots 开始对堆中对象进行可达性分析,找到存活的对象,这阶段耗时较长,但是可以和用户线程并发运行。最终标记阶段则是为了修正在并发标记期间因用户程序继续运行而导致标记产生变化的那一部分标记记录,虚拟机将这段时间对象变化记录在线程 Remembered Set Logs 里面,最终标记需要把 Remembered Set Logs 的数据合并到 Remembered Sets 中,这阶段需要暂停线程,但是可并行执行。最后的筛选回收阶段首先对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来确定回收计划。G1 收集器运行示意图如下图所示。


2、G1 分区的概念

G1 的堆区在分代的基础上,引入分区的概念。G1 将堆分成了若干 Region,以下和”分区”代表同一概念。(这些分区不要求是连续的内存空间)Region 的大小可以通过 G1HeapRegionSize 参数进行设置,其必须是 2 的幂,范围允许为 1Mb 到 32Mb。 JVM 的会基于堆内存的初始值和最大值的平均数计算分区的尺寸,平均的堆尺寸会分出约 2000 个 Region。分区大小一旦设置,则启动之后不会再变化。如下图简单画了下 G1 分区模型。



Eden regions(年轻代-Eden 区)


Survivor regions(年轻代-Survivor 区)


Old regions(老年代)


Humongous regions(巨型对象区域)


Free regions(未分配区域,也会叫做可用分区)-上图中空白的区域


G1 中的巨型对象是指,占用了 Region 容量的 50%以上的一个对象。Humongous 区,就专门用来存储巨型对象。如果一个 H 区装不下一个巨型对象,则会通过连续的若干 H 分区来存储。因为巨型对象的转移会影响 GC 效率,所以并发标记阶段发现巨型对象不再存活时,会将其直接回收。ygc 也会在某些情况下对巨型对象进行回收。


分区可以有效利用内存空间,因为收集整体是使用“标记-整理”,Region 之间基


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


于“复制”算法,GC 后会将存活对象复制到可用分区(未分配的分区),所以不会产生空间碎片。

[](

)3、G1 GC 的分类和过程


JDK10 之前的 G1 中的 GC 只有 Young?GC,Mixed?GC。Full?GC 处理会交给单线程的 Serial Old 垃圾收集器。

[](

)4、Young?GC 年轻代收集


在分配一般对象(非巨型对象)时,当所有 Eden region 使用达到最大阀值并且无法申请足够内存时,会触发一次 Young?GC。每次 Young?GC 会回收所有 Eden 以及 Survivor 区,并且将存活对象复制到 Old 区以及另一部分的 Survivor 区。到 Old 区的标准就是在 PLAB 中得到的计算结果。因为 Young?GC 会进行根扫描,所以会 stop the world。


Young?GC 的回收过程如下:


1、根扫描,跟 CMS 类似,Stop the world,扫描 GC Roots 对象。

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
说一下 jvm 有哪些垃圾回收器?,kalilinux渗透教程百度云