У меня есть функция Kotlin с этой подписью:
fun registerDisposer(obj: Any, disposer: Closeable)
Что делает функция, так это прикрепляет disposer
к фантомной ссылке и организует ее закрытие, когда obj
удаляется сборщиком мусора (т. е. когда объект фантомной ссылки ставится в очередь). Класс obj
должен называть это примерно так:
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()
}
})
}
}
(Давайте проигнорируем, стоит ли полагаться на это с помощью общих Closeable
s; фактически рассматриваемый ресурс — это указатель, управляемый нативным/JNI-кодом — я пытаюсь следовать совету Ганса Бема. Но все это не имеет особого отношения к этому вопросу.)
Меня беспокоит, что этот дизайн слишком упрощает непреднамеренную передачу объекта, который захватывает this
из внешней области, создавая цикл ссылок и вообще предотвращая сборку мусора для объекта:
registerDisposer(this, Closeable {
this.res1.close()
this.res2.close()
})
Могу ли я добавить аннотацию к параметру disposer
, которая вызовет предупреждение в этой ситуации?
На момент написания этой статьи ответ кажется таким: вероятно, нет.
Оказывается, функция registerDisposer
уже существует как register
метод java.lang.ref.Cleaner
, и у нее нет такой аннотации.
В Android есть аналогичная аннотация для android.os.AsyncTask
, но она просто предупреждает любой анонимный объект, имеющий AsyncTask
в качестве базового класса, независимо от того, захватывает он this
или нет. (Это имеет смысл в Java, где анонимные классы всегда захватывают this
, но не в Котлине.)