使用内联函数创建匿名对象。它是否包含封闭类的泄漏?

Bel*_*loo 5 memory-leaks kotlin

如您所知,java 中的每个匿名对象都包含对封闭类的隐藏引用。
但有了 kotling,事情就变得更加复杂了。

Lambda 是匿名类的另一种表示形式,但在 kotlin 中它的编译并不简单,因为如果 lambda 没有显式捕获封闭类的引用,那么它会像嵌套那样编译,而不是内部类(匿名类),并且不会泄漏。

但是内联函数呢?考虑下面的代码

class A {
    fun test(){
        val it = withReference {
            //todo make sth
        }
    }

}

inline fun withReference(crossinline action: () -> Unit) = object: Reference {
    override fun method1() {
        action()
    }
    override fun method2() {
    }
}

interface Reference {
    fun method1()
    fun method2()
}
Run Code Online (Sandbox Code Playgroud)

据我所知,内联函数会像非包装代码一样编译到 A 类,所以问题是开放的。

匿名是否object: Reference包含指向封闭类的链接A,这可能导致内存泄漏?

PS:我已阅读this article,但它不包含我的情况的答案

zsm*_*b13 2

如果您考虑一下,该withReference函数无法引用它内联到的外部作用域,因此它没有理由包含对其调用的作用域的引用。您甚至不知道它在哪个类中被调用,或者甚至不知道它是否在类内被调用。

对于这种特定情况,这是该函数的反编译和简化的字节码withReference

public static Reference withReference(final Function0 action) {
    return new Reference() {
        public void method1() {
            action.invoke();
        }

        public void method2() {
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

在它被内联的地方,当然没有调用这个函数,这个函数仅用于 Java 互操作。Kotlin 调用站点都会生成自己的类来表示该对象,具体取决于您传递给action参数的代码。对于函数的调用test,会生成一个类似的类:

public final class A$test$$inlined$withReference$1 implements Reference {
    public void method1() {
        //todo make sth
    }
    public void method2() {
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是该test方法中实例化的内容:

public final class A {
    public final void test() {
        Reference it = new A$test$$inlined$withReference$1();
    }
}
Run Code Online (Sandbox Code Playgroud)