一、Lua 的垃圾回收机制
Lua 语言使用自动内存管理, 无需像 C、C++ 语言进行手动内存管理。
但是和 java、kotlin 一样,有时也需要外部进行辅助回收,区分哪些资源是可以进行回收的。
在 Lua 种主要用来辅助垃圾回收的主要机制有:
- 弱引用表
- 析构器
- collectgarbage 函数
二、弱引用表
1、Lua 的弱引用
在 java、kotlin 中有 “强软弱虚” 四种引用类型,Lua 则有 “强弱” 引用类型。
Lua 中正常设置的值,即有变量直接引用的值,则为强引用,垃圾回收机制不会对其进行回收。
Lua 的另一种引用类型则是弱引用,垃圾回收机制只要运行就会对弱引用进行回收,而 Lua 的弱引用以弱引用表的形式存在。
Lua 的这两种引用类型和 java、kotlin 中对应的 “强”、“弱” 引用的生命周期是一致的
表 table 有键值对,只要键值对中有一个为弱引用,则该表就为弱引用表,所以简单来说弱引用表有三种存在形式:弱引用键的表、弱引用值的表、弱引用键弱引用值的表。
弱引用表的声明是通过元表,元表中设置 “__mode” 字段,对应关系如下表
弱引用表类型 | __mode 取值 |
---|---|
弱引用键的表 | “k” |
弱引用值的表 | “v” |
弱引用键弱引用值的表 | “kv” |
值得说明的是,弱引用表只要键值对中有一个值没有被外部其他的非弱引用进行引用,则该键值对就被垃圾回收机制回收掉。 即只要存在强引用的话,该被引用的对象就还是不会被回收,如果该对象只是被多个弱引用进行引用的话,则会被回收。
举个例子:
如果不使用弱引用表,即使运行 collectgargabe
函数进行垃圾回收,也不会释放
local a = {
}
local k1 = {
}
a[k1] = 10
local k2 = {
}
a[k2] = 20
print("移除引用前:")
for i, v in pairs(a) do
print(i, v)
end
--> 移除引用前:
--> table: 0x60000200c9c0 10
--> table: 0x60000200c980 20
print("移除引用后:")
k1 = nil
k2 = nil
-- 垃圾回收
collectgarbage()
for i, v in pairs(a) do
print(i, v)
end
--> 移除引用后:
--> table: 0x60000200c9c0 10
--> table: 0x60000200c980 20
使用了弱引用表:
这里会对 k1 赋值为 nil
,即中断了 k1 对 table 的强引用,只剩下弱引用对该 table 的引用,所以在使用 collectgarbage
进行回收,弱引用表也会中断了该 table 的引用,使其被回收。
local a = {
}
-- 创建一个 key 为弱引用的表
local mt = {
__mode = "k" }
setmetatable(a, mt)
local k1 = {
}
a[k1] = 10
local k2 = {
}
a[k2] = 20
print("移除引用前:")
for i, v in pairs(a) do
print(i, v)
end
--> 移除引用前:
--> table: 0x60000200ca80 10
--> table: 0x60000200cac0 20
print("移除引用后:")
-- 删除值
k1 = nil
-- 垃圾回收
collectgarbage()
for i