首页 > 编程知识 正文

jvm常见的垃圾回收算法,jvm垃圾回收算法和垃圾回收器

时间:2023-05-04 21:52:18 阅读:190104 作者:1880

垃圾回收是如何识别垃圾的(1)引用计数(2)可路由算法常见的垃圾回收算法屏幕(ddbm-sweap )复制)标记压缩(ddbm )

#白话

什么是垃圾未引用的对象

如何查找垃圾(1)每个引用计数对象都有引用计数属性,添加引用时计数增加1,释放引用时计数减少1。 (注:无法解决循环引用问题)

Object objectA=new Object (; Object objectB=new Object (; objectA.instance=objectB; objectB.instance=objectA; objecta=空; objectb=空; 程序启动后,将创建两个对象: objectA和objectB,并为堆分配内存。 这些对象相互之间有对方的引用,但除了相互之间的引用以外没有其他引用。 实际上,引用已经为空,无法访问这两个对象,但由于它们相互引用,引用计数不为0,因此引用计数算法无法通知GC回收它们,从而造成内存浪费

)2)路线可到达算法的概念)通过根对象(下路径GC路线)的参照探索,最终可到达的对象是可到达的对象,可到达的对象是存在参照的对象,相反,是不可到达的对象

```

典型的垃圾回收算法屏幕(ddbm-sweap ) )。

特点:

算法简单,生存对象比较高时效率高(根遍历生存对象多,需要清理的对象比较少)---- -不适合伊甸园区清理,伊甸园区生存对象比较少。

问题:

1-2遍扫描效率低下(将第一次扫描中不可重用的对象标记为“根”(root )标记为存活对象,第二次清除未标记的对象)。

容易发生2-碎片(清理的内存空间不是连续的) ) ) ) ) ) ) ) ) ) ) )2-碎片) ) ) ) 65 )

复制(复印)

方法:将存储器分成两块,一次只使用一个块,GC时,将使用中的存储器中的存活对象复制到另一个存储空间,清除使用中的空间中的所有对象

缺点:浪费空间,移动复制的对象,需要调整对象引用

总结:在生存对象较少的情况下使用。 只扫描一次,效率就会提高,碎片就会消失。 适用于Eden区。

标记(ddbm-compact ) ) ) )。

方法:首先标记所有可路由对象(引用所在的对象)。 不同之处在于,标记完成后,将所有已标记对象(即存活对象)压缩到内存空间的边缘,然后清理边界外的所有空间,而不是直接移除未标记的垃圾对象

特征:扫描两次(第一次标记索引根可到达对象,第二次移动),需要移动对象。

优点:不出现碎片,内存分配方便,内存不减半

jvm分代模型(仅限分代垃圾回收算法) ZGC Shenandoah这些不适用于分代模型。 G1逻辑上划分世代,物理上不划分世代(垃圾收集器的种类参照下一节),除此之外不仅逻辑上划分世代,而且物理上划分世代,积累存储器逻辑分区

现在需要添加一点运行时数据区的知识。 https://blog.csdn.net/u 010488116/article/details/79800142

图: 1、年轻一代分为一个Eden区和两个Surviver区,比例为8:1:1,两个Surviver区分别称为“From”区和“To”区。 对象是在Eden区域创建的,一旦通过Yong GC,仍存活的对象将被复制到Surviver区域的“从”区域。 “到”区域是空的。 到了下一个GC时,在Eden区仍然存在的对象会直接移动到Surviver区的" To "区,但" Form "区的对象有两个目的地," From "区的对象根据经过的GC次数计算年龄否则,将被复制到“tto”。然后,“从”和“到”区域将进行角色交换,直到下一次进行GC时为止,将显示用于保存从“从”和“从”区域移动来的对象的空的“” (请注意,自from和to首次gc以来,未满年龄的对象将往返于from和to之间进行交换。)

YGC/minor gc :年轻一代的空间消失时

Major GC/Full GC :在旧年代不能分配空间的情况下触发,新一代、旧年代同时被回收

一个对象分配过程

注意:

并不是所有出现new的对象都被分配给堆。 不分配给堆的特殊情况:分配给TLAB和堆栈。

为什么?

使用new关键字为堆分配对象时,必须将其锁定,因为您知道堆是所有线程共享的,而且它是冲突资源,并且必须与冲突资源进行必要的同步。 既然有上锁,就一定会存在上锁引起的额外开销,而且为了对整个堆上锁,上锁的粒度相对较大,频繁地分配对象的话就不可避免地会影响效率。

因此,在某些情况下,您可以避免将对象分配给堆,以提高创建和销毁对象的效率。

分配给堆栈的new对象是什么?

堆栈上的分配

线程专用迷你对象

–无逃逸(只在某段代码使用)eg:一个对象的方法里面就一句new Object(),没有任何引用指向它),如果有外部引用指向它就会有逃逸。
–支持标量替换 eg 一个对象里面只有 int a, int b,使用普通类型直接代替对象
·线程本地分配(Thread-local allocation buffer)
–占用eden,默认1%
多线程的时候不用竞争eden就可以申请空间,(eden区,多线程情况都想往一个地址分配对象,效率会降低)提高效率
小对象

常见垃圾回收器 serial


STW:在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(只有gc线程工作)
缺点:stw时间太长,停顿时间太长,内存空间太大导致清理时间会变长。(以前是扫屋子,现在扫整个省)

serial old


使用ddbm sweap 或ddbm compact算法,也是单线程

Parallel Scavenge


多GC线程处理垃圾(就是喊些强健的指甲油和你一起扫大街,行人都给我旁边捎着去)

Parallel Old


使用多线程ddbm compact算法的垃圾回收器

parNew

它实际是Serial GC的多线程版本

PS 和 PN区别的延伸阅读: ▪https://docs.oracle.com/en/java/javase/13/gctuning/ergonomics.html#GUID-3D0BB91E-9BFF-4EBB-B523-14493A860E73

CMS

垃圾回收线程和工作线程同时进行。(一边扔垃圾一边捡垃圾),因无法忍受stw产生。
cmsGC标记有七个阶段,主要了解上图四个阶段
初始化标记阶段:,也是标记阶段的开始。主要工作是 标记可直达的存活对象 。(注:第一阶段只标记了老年代最根上的对象)

并发标记:通过遍历第一个阶段(Initial Mark)标记出来的存活对象,继续递归遍历老年代,并标记可直接或间接到达的所有老年代存活对象

重新标记:在并发标记的期间又重新产生的垃圾,停止工作线程,新产生的垃圾不多,因此stw时间很短。
并发清理:在清理的过程中产生的垃圾称为浮动垃圾,下一次cms清理过程清理

缺点:CMS 和 serial old配合使用
(老年代碎片划严重,老年代满了的时候,使用serial old – 单线程gydwt进行清理,32g内存清理太慢了)解决方案:降低触发cms阈值。
问题:
内存碎片话(使用的是ddbm sweap)
产生浮动垃圾

todo G1 ZGC

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。