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,但它不包含我的情况的答案
如果您考虑一下,该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)
| 归档时间: |
|
| 查看次数: |
971 次 |
| 最近记录: |