为什么继承PhantomReference会阻止对象被清理

问题描述 投票:0回答:1

我想在附加的java对象清理后释放本机资源。

我想提供额外的变量进行清理,所以我继承了 PhantomReference。但该引用并未排队到 ReferenceQueue 中。

这是我使用 Kotlin/JVM 的最小示例

val queue = ReferenceQueue<Any>()
var obj: Any? = Any()

val phantomRef = PhantomReference(obj!!, queue) // this works!!
// val phantomRef = object: PhantomReference<Any>(obj!!, queue) {} // this does not works even there are no extra fields :(

println("Created PhantomReference")

obj = null // Clear strong reference
System.gc() // Trigger garbage collection

Thread.sleep(1000) // Wait for GC

val ref = queue.poll()
if (ref != null) {
    println("PhantomReference enqueued!")
} else {
    println("PhantomReference not enqueued.")
}

编辑 我又发现了一个奇怪的案例:

// this works
val phantomRef = PhantomReference(obj!!, queue)

// this does not works
PhantomReference(obj!!, queue)

我认为这可能与优化有关,但我不确定

这是由 PhantomReference 主导的,它本身也被 GC 了,但不幸的是,这并不能解决主要问题。

感谢@user85421指出这一点。

kotlin jvm phantom-reference
1个回答
0
投票

感谢@Slaw,我解决了我的问题。

val queue = ReferenceQueue<Any>()

val refs = mutableListOf<PhantomReference<Any>>()

repeat(100) {
    var obj: Any? = Any()
    refs.add(object: PhantomReference<Any>(obj!!, queue) {})
    obj = null // Clear strong reference
    System.gc() // Trigger garbage collection

    Thread.sleep(10000) // Wait for GC
    val ref = queue.poll()
    if (ref != null) {
        println("PhantomReference enqueued!")
    } else {
        println("PhantomReference not enqueued.")
    }
}

这是我的新代码和参考,在每次第二次迭代时排队。(我不知道为什么它是每次第二次迭代,但至少它完成了它的工作)

© www.soinside.com 2019 - 2024. All rights reserved.