unity-tolua之释放引用实测

unity-tolua之释放引用实测, 主要是验证是否能够解开 lua 与 csharp 之间的引用, 进而被对应 gc 回收.


前篇

目的是测试 csharp 中的 lua 相关导出变量在不 Dispose 的情况下是否会解引用, 进而被 gc.


相关测试代码

  • csharp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class CDog : MonoBehaviour {
    public LuaFunction luaCellCreateFn;

    void OnDestroy() {
    if (luaCellCreateFn != null) {
    luaCellCreateFn.Dispose(); // 主要是测试 Dispose
    luaCellCreateFn = null;
    }
    }
    }
  • lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
        -- 类定义
    local CGm = class()
    CGm.__name = "CGm"

    function CGm.Init(self)
    end

    return CGm


    -- lua 对象被回收会调用这个函数, obj 是实例对象, 这个代码就不贴那么细了
    function _luaObjGc(obj)
    local type_id = obj.__name
    if type_id then
    gLog("--- _luaObjGc, name: {0}", type_id)
    end
    end

    --- 测试逻辑
    function _test()
    local testIns = require("gm"):New() -- 创建 CGm 实例

    local dog = GameMgr.Ins:AddComponent("CDog")
    dog.luaCellCreateFn = function() -- 绑定 lua 方法到 csharp 中
    testIns:Init() -- 引用住 testIns
    end
    end



    ---

    ### 确定实例对象及方法都是引用住的

    1. 执行 `_test` 方法, 会往 go 上挂一个 `CDog` 实例组件, 同时 绑定了 `luaCellCreateFn` 方法, `luaCellCreateFn` 方法右引用住了 `testIns` 实例

    2. 触发 lua gc 几次

    ![](https://pic04.wilker.cn/20211211172815-1.webp)

    没有发现 `testIns` 实例被回收的日志, 这是正确的, 因为被引用住了



    ---

    ### 不 Dispose LuaFunction

    1. 注释掉 csharp 中 `CDog` 的 `OnDestroy` 方法中的 `luaCellCreateFn.Dispose();` 代码

    2. 在 lua 中销毁 dog 实例

    ```json
    GameObject.Destroy(dog)
  1. 触发 lua gc 几次 (不要太多次, 不要触发到 csharp 的 gc)

    发现了其他 lua 实例被回收的日志, 但没有发现 testIns 实例被回收的日志

  2. 触发 csharp gc 几次 再触发 lua gc 几次

    发现 testIns 实例被回收的日志

    原因是因为 csharp 中 CDog 实例被 gc 后, 才会调用到 tolua 框架的 析构函数 进行解引用, 解引用完后绑定到 luaCellCreateFn 的 lua 方法才被释放, 然后进一步回收 testIns 实例


主动 Dispose LuaFunction

  1. 打开 csharp 中 CDogOnDestroy 方法中的 luaCellCreateFn.Dispose(); 代码

  2. 在 lua 中销毁 dog 实例

    1
    GameObject.Destroy(dog)
  3. 触发 lua gc 几次

    发现 testIns 实例被回收的日志, 而且还在其他 lua 实例被回收之前

    原因是因为 CDogOnDestroy 方法中的 luaCellCreateFn.Dispose(); 代码, 主动解开了 lua 中绑定的 luaCellCreateFn 方法引用, 然 lua gc 时就可以立马释放 luaCellCreateFn 方法 及 testIns 实例


结论

在 csharp 中不主动 Dispose lua 方法/table 都是没问题的, 只是被回收的时间会比较长

如果主动 Dispose, 就能及时回收 lua 实例.

by the way, 养成良好习惯, 在不使用时都主动置空 (lua 置为 nil, csharp 置为 null)