Search code examples
kotlinannotationsreference-cycle

Is there an annotation that triggers a warning if an object is passed that captures enclosing ‘this’?


I have a Kotlin function with this signature:

fun registerDisposer(obj: Any, disposer: Closeable)

What the function does is attach disposer to a phantom reference and arrange it to be closed when obj is garbage-collected (i.e. when the phantom reference object is enqueued). The class of obj is supposed to call it something like this:

class Holder(private val res1: Closeable, private val res2: Closeable) {
    init {
        registerDisposer(this, object: Closeable {
            private val res1 = [email protected]
            private val res2 = [email protected]

            override fun close() {
                res1.close()
                res2.close()
            }
        })
    }
}

(Let’s ignore whether this is a good idea to rely on this with general Closeables; the actual resource in question is a pointer managed by native/JNI code – I am trying to follow Hans Boehm’s advice. But all of this is not particularly relevant for this question.)

I am worried that this design makes it too easy to inadvertently pass an object that captures this from the outer scope, creating a reference loop and preventing the object from being garbage-collected at all:

registerDisposer(this, Closeable {
    this.res1.close()
    this.res2.close()
})

Is there an annotation I can add to the disposer parameter that will trigger a warning in this situation?


Solution

  • As of this writing, the answer seems to be: probably not.

    It turns out a registerDisposer function already exists as the register method of java.lang.ref.Cleaner, and it has no such annotation.

    In Android, there is a similar annotation for android.os.AsyncTask, but that simply warns at any anonymous object having AsyncTask as its base class, whether it captures this or not. (This makes sense in Java, where anonymous classes always capture this, but not in Kotlin.)