欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java 垃圾回收机制 (分代垃圾回收ZGC)

程序员文章站 2022-05-03 13:55:58
什么是自动垃圾回收? 自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何指针给指向,因此占用的内存也可以被回收掉。 在用 C 之类的编程语言时,程序员 ......

什么是自动垃圾回收?

自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何指针给指向,因此占用的内存也可以被回收掉。

在用 c 之类的编程语言时,程序员需要自己手动分配和释放内存。而 java 不一样,它有垃圾回收器,释放内存由回收器负责。本文接下来将介绍垃圾回收机制的基本过程。

 

第一步:标记

这个过程的第一步叫做标记。这一阶段,垃圾回收器识别哪些内存正在使用,哪些内存未被使用。

Java 垃圾回收机制 (分代垃圾回收ZGC)

被引用的对象以蓝色展示。未被引用的对象以金黄色展示。在标记阶段,所有对象都需要扫描并做出判断。如果系统中的所有对象都必须扫描到,这将是一个非常耗时的过程。

第二步:清除

这一步会删掉标记出的未引用对象。Java 垃圾回收机制 (分代垃圾回收ZGC)

内存分配器会保留指向可用内存的引用,以供分配新对象。

压缩

为了提升性能,删除了未引用对象后,还可以将剩下的已引用对象放在一起(压缩),这样就能更简单快捷地分配新对象了。Java 垃圾回收机制 (分代垃圾回收ZGC)

为什么使用分代垃圾回收?

如前所述,标记并整理所有jvm里的对象,效率是很低的。随着越来越多的对象被分配,对象列表不断增长,导致垃圾回收时间越来越长。然而,根据应用程序的经验分析,大多数的对象都是短命的。

下面是这类数据的一个例子。y轴表示分配的字节数,x轴表示随着时间分配的字节数。

Java 垃圾回收机制 (分代垃圾回收ZGC)

正如你所看到的,随着时间的推移,仍然存活的对象越来越少。事实上,大多数对象的生命周期都很短,如图左侧较高的值所示。

 

jvm 分代

根据之前的规律,就可以用来提升 jvm 的效率了。方法是,把堆分成几个部分(就是所谓的分代),分别是新生代、老年代,以及永生代。Java 垃圾回收机制 (分代垃圾回收ZGC)

新对象会被分配在新生代内存。一旦新生代内存满了,就会开始对死掉的对象,进行所谓的小型垃圾回收过程。一片新生代内存里,死掉的越多,回收过程就越快;至于那些还活着的对象,此时就会老化,并最终老到进入老年代内存。

stop the world 事件 —— 小型垃圾回收属于一种叫 "stop the world" 的事件。在这种事件发生时,所有的程序线程都要暂停,直到事件完成(比如这里就是完成了所有回收工作)为止。

 

老年代用来保存长时间存活的对象。通常,设置一个阈值,当达到该年龄时,年轻代对象会被移动到老年代。最终老年代也会被回收。这个事件成为 major gc。

major gc 也会触发stw(stop the world)。通常,major gc会慢很多,因为它涉及到所有存活对象。所以,对于响应性的应用程序,应该尽量避免major gc。还要注意,major gc的stw的时长受年老代垃圾回收器类型的影响。

永久代包含jvm用于描述应用程序中类和方法的元数据。永久代是由jvm在运行时根据应用程序使用的类来填充的。此外,java se类库和方法也存储在这里。

如果jvm发现某些类不再需要,并且其他类可能需要空间,则这些类可能会被回收。

 

分代垃圾回收过程

既然已经了解了为什么将堆分成不同的代,现在就该看看这些空间到底是如何交互的。下面的图片展示了jvm中对象分配和老化的过程。

首先,任何新对象都在eden区分配。两个survivor区都是空的。

Java 垃圾回收机制 (分代垃圾回收ZGC)

当eden区满了,触发一次minor gc。

Java 垃圾回收机制 (分代垃圾回收ZGC)

被引用的对象被移动到第一个survivor区,未被引用的对象会在eden区清除时一并删除。

Java 垃圾回收机制 (分代垃圾回收ZGC)

 

在下一次minor gc中,eden区也会做同样的操作。删除未被引用的对象,并将被引用的对象移动到survivor区。然而,这里,他们被移动到了第二个survivor区(s1)。此外,第一个survivor区(s0)中,在上一次minor gc幸存的对象,会增加年龄,并被移动到s1中。待所有幸存对象都被移动到s1后,s0和eden区都会被清空。注意,survivor区中有了不同年龄的对象。

Java 垃圾回收机制 (分代垃圾回收ZGC)

在下一次minor gc中,会重复同样的操作。不过,这一次survivor区会交换。被引用的对象移动到s0,。幸存的对象增加年龄。eden区和s1被清空。

Java 垃圾回收机制 (分代垃圾回收ZGC)

 

此幻灯片演示了 promotion。 在较小的gc之后,当老化的物体达到一定的年龄阈值(在该示例中为8)时,它们从年轻一代晋升到老一代。

Java 垃圾回收机制 (分代垃圾回收ZGC)

随着较小的gc持续发生,物体将继续被推广到老一代空间。

Java 垃圾回收机制 (分代垃圾回收ZGC)

所以这几乎涵盖了年轻一代的整个过程。 最终,将主要对老一代进行gc,清理并最终压缩该空间。

Java 垃圾回收机制 (分代垃圾回收ZGC)