Golang内存管理--垃圾回收原理

所谓垃圾就是不再需要的内存块,这些垃圾如果不清理就没办法再次被分配使用,在不支持垃圾回收的编程语言里,

这些垃圾内存就是泄露的内存。

垃圾回收算法

  标记清除:从根变量开始遍历所有引用的对象,引用的对象被标记为“被引用”,没有被标记的被回收。

  引用计数:对每个对象维护一个引用计数,当引用该对象的对象被销毁时,引用计数减1,当引用计数器为0

垃圾回收的核心就是标记出哪些内存还在使用中(即被引用到),哪些内存不再使用了(即未被引用),把 未被引用的内存回收掉,以供后续内存分配时使用。

 

内存块124号位上的内存块已被分配(数字1代表已被分配,0 未分配)。变量a, b为一指针,指向内存 的12号位。内存块的4号位曾经被使用过,但现在没有任何对象引用了,就需要被回收掉。 垃圾回收开始时从root对象开始扫描,把root对象引用的内存标记为被引用,考虑到内存块中存放的可能是指针,所以还需要递归的进行标记,全部标记完成后,只保留被标记的内存,未被标记的全部标识为未分配即完成了回收。

内存标记

span中维护了一个个内存块,并由一个位图allocBits表示每个内存块的分配情况。在span数据结构中还有另一个位图gcmarkBits用于标记内存块被引用情况。

allocBits记录了每块内存分配情况,而gcmarkBits记录了每块内存标记情况。标记阶段对每块内存 进行标记,有对象引用的的内存标记为1(如图中灰色所示),没有引用到的保持默认为0. allocBitsgcmarkBits数据结构是完全一样的,标记结束就是内存回收,回收时将allocBits指向 gcmarkBits,则代表标记过的才是存活的,gcmarkBits则会在下次标记时重新分配内存。

三色标记法

这里的三色,指的是对应了垃圾回收过程中的三种对象的状态:

  灰色:对象在标记队列中等待

  黑色:对象已被标记,gcmarkBits对应的 1(该对象不会在本次GC中被清理)

  白色:对象未被标记,gcmarkBits对应的 0 (该对象会在本次GC中被清理)

  当前内存中有A~F一共6个对象,根对象a,b本身为栈上分配的局部变量,根对象ab分别引用了对象AB, B对象又引用了对象D,则GC开始前各对象的状态如下图所示:

  初始状态下都是白色的。

  紧接着开始扫描根对象a,b

  由于根对象引用了对象AB,那么AB变为灰色对象,接下来就开始分析灰色对象,分析A时,A没有引用其他对象很快就转入黑色,B引用了D,则B转入黑色的同时还需要将D转为灰色,进行接下来的分析。

  上图中灰色对象只有D,由于D没有引用其他对象,所以D转入黑色。标记过程结束:

  最终,黑色的对象会被保留下来,白色的会被回收。

 

 

 

posted @ 2023-05-10 23:38  99号的格调  阅读(31)  评论(0编辑  收藏  举报