# Finalizer
# 相关数据结构
当垃圾回收释放一个对象的时候,会看看这个对象有没有设置finalizer ,如果有,就会执行这个finalizer 然后再释放对象。比如,给文件相关的结构添加一个finalizer,当对象被释放的时候,finalizer 会关闭相关的文件描述符。
golang 提供了对应的接口给开发人员,开发者可以通过SetFinalizer 方法给对象加上finalizer。

上图是存储finalizer相关的结构specialfinalizer,specialfinalizer 中的fn 就是finalizer 函数的指针,specialfinalizer会被挂在对象所在mspan的specials这条链表中,每次进行扫描阶段的时候,都要标记specialfinalizer 结构中的指针(fn)指向的地址,同时还要标记对应的对象(对象在mspan中的位置可以通过offset找到),以免finalizer 运行依赖的对象被回收。当清扫mspan的时候,发现某个对象可以被释放了,也不会立马执行finalizer(立马执行也可以,但是会增加清扫的时间),而是把specialfinalizer 转成下图的finalizer 然后放到finblock中。后台会有一个专门的go routine 会从finblock 中取出 finalizer 一个个执行。

在垃圾回收的扫描阶段,finblock同样需要被扫描(对fin这个数组里边finalizer中的指针指向的地方进行标记)。
ot 的作用主要是当fint是interface类型的时候(也就是finalizer函数接受的参数是一个interface),ot 可以和 arg 组成一个 interface。
# finalizer 执行方式
finalizer 运行使用的是 reflectcall 这个方法,如下图所示。

argtype 和 写屏障有关,在执行finalizer的场景下,这个填nil就行了。fn,arg 分别指向函数和参数的其实位置,argszie 和 retoffset 分别是 参数的大小和 返回值基于参数起始地址的偏移

上图是golang的calling convention,golang函数调用把参数和返回值都放在栈中(图中的args from caller 和 args to callee 就包括了参数和返回值)
