算法 自动采集列表( jvm怎么知道堆里面的对象是无用数据,的基本算法)
优采云 发布时间: 2021-12-25 18:19算法 自动采集列表(
jvm怎么知道堆里面的对象是无用数据,的基本算法)
jvm的三种算法和10个垃圾采集
器
jvm如何知道堆中的对象是无用数据,有两种方式:
1.引用计数方法:
每个对象都有一个引用计数属性,新的引用计数加1,引用释放时计数减1,计数到0就可以回收。这种方法简单,不能解决循环引用的问题对象之间。
2. 关注GC Roots
(可达性分析):从GC Roots开始向下搜索,搜索所经过的路径称为参考链。当一个对象没有通过任何引用链连接到GC Roots时,证明该对象不可用,即不可达对象。
jvm的三种基本算法
1.1 标记-扫描算法(Mark-Sweep)
一块内存,要恢复的数据,直接标记,清除
1.2 复制算法(Copying)
将一块内存中的数据直接复制到另一块内存中,然后清理之前的内存区域
1.3 Mark-Compact 算法(Mark-Compact)
将内存中的数据移动并标记到内存一侧进行清理
1.4 代采集
算法
注意,这个算法是根据不同代的对象被清除时使用的算法,将内存堆从物理上和逻辑上划分为年轻代和老年代的一种算法
10种垃圾采集
器
算法就是GC的垃圾采集
的策略,垃圾采集
器就是按照算法进行垃圾处理的具体实现。
2.1 个串行采集
器
串行(serial)垃圾采集
器是最基础的采集
器,发展历史最长;
JDK1.3.1是新一代HotSpot合集的唯一选择;
串行采集
器直到JDK1.7,它仍然是运行在Client模式下的JAVA虚拟机默认的新一代采集
器。它也有优于其他采集
器的优点:简单高效(相对于其他采集
器的单线程)。对于仅限于单个 CPU 的环境,Serial 采集
器没有线程交互开销,因此专注于垃圾采集
是很自然的。获得最高的单线程采集
效率。在用户的桌面应用场景中,分配给虚拟机管理的内存一般不会很大,采集
新一代的几十兆甚至一两百兆(只有新一代使用的内存,桌面应用基本没有大),暂停时间可以控制在几十毫秒以内,最多一百毫秒。只要不经常发生,这种停顿是可以接受的。因此,Serial采集
器是运行的不错选择。
Serial采集
器的运行图如下: stw:stop-the-word 停止所有工作线程;使用复制算法;
注意:这个采集
器,随着内存越来越大,执行效率太慢。比如一个人刚开始住在5平方米的房子里,房子打扫得很快。住500平米的房子,打扫屋子的时间过长,这种单线程不能用,以后会有多线程版本-ParNewcollector
2.2 系列老采集器
和Serial相比,Serial Old是老年代用的垃圾采集
器,也是单线程的,不过算法不是copy,而是Mark-Compact标记排序算法,也是stw:暂停所有线程为垃圾采集
;
所以Serial和Serial Old的结合,在服务器环境下可用内存一般都不大(几十M到一两百M),不适合现在的大内存
2.3ParNew 采集
器
ParNew 垃圾采集
器是串行采集
器的改进多线程版本(因为内存不断增加)。除多线程外,其余行为和特性与串行采集
器相同。实现算法与Serial(复制算法)完全相同。在stw下执行;
但是如果CPU数量为1或小于4,这种类型的采集
器的性能不会比Serial好。因为去掉了上下文切换,占用了用户线程的CPU时间片,导致用户线程变慢
在Server模式下,ParNew采集
器是一个非常重要的采集
器,因为除了Serial之外,目前只能和CMS采集
器配合使用;CMS是在JDK1.5中推出的HotSpot的第一个真正含义,互联网上的并发(Concurrent)采集
器第一次使垃圾采集
线程与用户线程(基本)同时工作;
1)CMS是老年代的采集
器,但是不能和JDK1.4中已经存在的新一代采集
器Parallel Scavenge一起工作;
2) 因为Parallel Scavenge(和G1)不使用传统的GC采集
器代码框架,而是独立实现;而其他类型的采集
器共享部分框架代码;
设置参数
"-XX:+UseConcMarkSweepGC":指定使用CMS后,默认使用ParNew作为新一代采集
器;
“-XX:+UseParNewGC”:强制指定使用ParNew;
“-XX:ParallelGCThreads”:指定ParNew默认开启的垃圾回收线程数、回收线程数和CPU数
2.4.并行老
这是 Serial Old 的多线程版本。它用于老年代的采集
器。它也是一种mark-and-sort算法,是stw的执行集合。但如果 CPU 数量少,性能同样糟糕。但现在PC或服务器CPU的数量不再是性能瓶颈限制,所以目前它与Parallel Scavenge的合作是吞吐量优先场景的首选采集
器选择。
2.5Parallel Scavenge
相比ParNew,无法与cms结合的新一代垃圾采集
器。PS也是一种复制算法。它与前两个采集
器的最大区别在于它专注于吞吐量而不是延迟。也称为吞吐量优先采集
器。其中,吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾采集
时间)。
主要使用场景:主要适用于后台计算而不是过多的交互任务。高吞吐量可以最有效地利用CPU时间,尽快完成程序计算任务。当然,如果要减少暂停时间,吞吐量也会相应受到影响。
2.6 内容管理系统
CMS,Concurrent Mark Sweep,这是一个真正的并发采集
器,即在线程执行过程中也可以进行垃圾采集
的采集
器。在一些对响应时间要求高的应用或网站中,用户程序不能有长时间的停顿,在这种场景下可以使用CMS。分为四个过程,1个初始标记,2个并发标记,3个重新标记,4个并发清理
CMS执行流程图
CMS采用多种方式尽可能减少GC的暂停时间,减少用户程序的暂停。
在减少暂停时间的同时,牺牲了 CPU 吞吐量。因为并发占用了大量的cpu资源
这是暂停时间和性能的权衡,可以简单理解为时间的“空间(性能)”
CMS是一个连接过去和未来的采集器
以下是非分代采集
器
2.7 G1(垃圾优先)
在JDK7中,它加入了JVM采集
器家族,成为HotSpot的关键垃圾采集
技术。和优秀的CMS垃圾采集
器一样,G1也是一个专注于最小延迟的垃圾采集
器。也适用于大容量堆内存的垃圾回收。官方推荐使用G1,而不是选择CMS。G1最大的特点就是引入了partition的思想,弱化了代的概念,合理利用了垃圾采集
各个周期的资源,解决了其他采集
器甚至CMS的很多缺陷。
G1采集
器是一个垃圾采集
器,比之前的更好,有真正的突破。其实G1中还是保留了代的概念,但实际上新生代和老年代并没有物理上的分离。在 G1 中,内存空间被划分为区域。所谓新生代和老年代是由区域组成的。同时,G1 不需要与其他采集
器配合使用,它可以自己处理所有内存区域。总的来说,它不是一代采集器
,而是一款一体式采集器
。这也是JVM内存管理和垃圾回收的一个发展趋势。我们可以从下面的 zgc 中更清楚地看到这种变化。
G1采用mark-organize算法,避免CMS内存碎片问题,实现垃圾时间可控。它是一个优秀的采集器
。即便如此,从2004年第一篇论文发表到实际商用,也是jdk1.7。实施并不那么容易。
G1的工作过程:
初始标记:这个过程类似于CMS的第一个过程,只是标记了与GC Root相关的对象。
并发标记:这个过程需要很长时间来分析GC Root对所有对象的可达性分析。从GC Root节点遍历所有对象会很耗时,实际上JVM并没有这样做。JVM 使用Remembered Set 来保存对象引用的调用信息。在可达性分析中,只需要同时遍历记忆集即可,不需要从根节点开始一一遍历。
最终标记:由于并发标记阶段,用户线程仍在工作,这会导致标记出现一些偏差。这时候就需要通过remembered set log来记录这些变化。在这个阶段,更改被合并到记忆集中。完成最后的标记。
过滤清除:通过标记排序算法,根据用户配置的回收时间,以及维护的优先级列表,先采集
取值最高的区域。采集
阶段基于标记组织和复制算法实现
2.8 ZGC
zgc 是 jdk11 中最新发布的垃圾采集
器。完全没有代的概念,先说一下它的优点,官方的就是不碎片化,时间可控,大堆。
学习连接
2.9 雪兰多
Shenandoah 是一个并发和并行的垃圾采集
器;和ZGC一样,它也是一个低暂停时间的垃圾采集
器,但是ZGC是基于彩色指针实现的,而Shenandoah GC是基于布鲁克斯指针的。
其实业界早就出现了低暂停GC,只是Java来的比较晚
Azul's Zing中的C4 GC土豪选择
oracle中的HotSpot ZGC JDK11选择
R说ZGC说他们抄了Azul,两者是等价的。
可以参考这篇文章了解如何连接
2.10 厄普西隆
Java 11 新的 Epsilon 垃圾采集
器
Epsilon(A No-Op Garbage Collector)垃圾采集
器控制内存分配,但不执行任何垃圾采集
。一旦java的heap用完,直接关闭jvm。设计的目的是提供一个完全负向GC的实现,分配有限的内存分配,最小化内存占用的消耗和内存吞吐量的延迟时间。一个好的实现是隔离代码更改,不影响其他 GC,将其他 JVM 代码更改到最少。
仅供参考
链接:Epsilon 学习链接
最后附上各采集器的组合流程图
终于找到一个很不错的博客,写了很多jvm的知识,可以去学习下
添加链接描述