1. 前言
Lua采用了自動(dòng)內(nèi)存管理,我們不需要?jiǎng)h除對象,Lua會(huì)自動(dòng)地刪除那些已經(jīng)成為垃圾的對象、
最重要的就是!當(dāng)我們在糾結(jié)c++在回收時(shí)的環(huán)形引用問題時(shí),Lua早就走在了前面,它沒有環(huán)形引用問題,當(dāng)要用到環(huán)形結(jié)構(gòu)時(shí),也能被正常回收。
垃圾回收器只會(huì)回收它認(rèn)為是垃圾的東西,所以當(dāng)我們使用棧的時(shí)候就會(huì)出現(xiàn)一個(gè)問題:我們以為我們不再使用的對象被回收了,但是其實(shí)它還沒有被回收。原因如下:棧通常是由一個(gè)數(shù)組和一個(gè)表示頂部的索引來實(shí)現(xiàn)的,這個(gè)數(shù)組的的有效部分總是向頂部擴(kuò)展,當(dāng)我們彈出一個(gè)數(shù)據(jù)時(shí),只是將頂部索引遞減,而那個(gè)數(shù)據(jù)仍留在數(shù)組中,那么這對于Lua來說就不是垃圾。同理,那些全局變量,雖然不再使用了,但是仍然不是垃圾,需要用戶手動(dòng)將它們賦值為nil,Lua才會(huì)釋放它們。
2. 弱引用table
當(dāng)我們數(shù)組中引用了一個(gè)對象,那么這個(gè)對象就無法被回收。為了解決這個(gè)問題,Lua引入了弱引用table。
2.1 什么是弱引用
弱引用就是會(huì)被垃圾回收器忽視的對象引用,如果一個(gè)對象的引用都是弱引用,那么這個(gè)對象就可以被回收了
2.2 弱引用table的種類
正常情況下,table的key和value都是強(qiáng)引用的。
所以提出了三種弱引用table
- 具有弱引用key的table
- 具有弱引用value的table
- 同時(shí)具有兩種弱引用的table
2.3 弱引用table的實(shí)現(xiàn)
它往往是通過元表中的__mode字段來決定的。
如果這個(gè)字段的值包含字母"k",是弱引用key
如果這個(gè)字段的值包含字母"v",是弱引用value

Lua只會(huì)回收弱引用table中的對象,數(shù)字和布爾值以及字符串是不可回收的。
2.4 弱引用table在對象屬性中的實(shí)現(xiàn)方式
當(dāng)我們不想將對象屬性存儲(chǔ)在table中,想保持屬性的私有性,我們可以將對象作為key,屬性作為key的value,又因?yàn)閗ey為對象,此時(shí)就會(huì)出現(xiàn)該對象無法回收的情況,所以這時(shí)候弱引用table有用處啦
3. 垃圾回收器
我先簡述一下垃圾回收器的流程,后面的源碼分析留到下一個(gè)博文再來講
Lua的垃圾回收周期共分為四個(gè)階段:標(biāo)記、整理、清掃、收尾 。
在標(biāo)記階段,Lua會(huì)首先將根集合中的對象標(biāo)記為活躍,然后將任何程序可以通過根節(jié)點(diǎn)訪問到的對象也標(biāo)記為活躍。
在整理階段,Lua會(huì)遍歷所有的userdata,找出未被標(biāo)記且有g(shù)c元方法的userdata,將它們標(biāo)記為活躍,并放入單獨(dú)的列表中。再根據(jù)所有的弱引用table刪除其未被標(biāo)記的key和value。
在清掃階段,Lua遍歷所有對象,如果當(dāng)前對象未被標(biāo)記,就收集它,否則清除它的標(biāo)記。
在收尾階段,根據(jù)上面生成的userdata列表來調(diào)用終結(jié)函數(shù)