A resource leak occurs when code retains a resource without releasing it. Database connections, I/O handles, memory, threads, and active concurrent tasks can remain held after cancellation or an early return. section 15.2.8 section 14.3
class DatabaseConnection : AutoCloseable {
fun write(s: String) = println("writing $s!")
override fun close() {
println("Closing!")
}
}
fun main() {
runBlocking(Dispatchers.Default) {
val dbTask = launch {
val db = DatabaseConnection()
delay(500.milliseconds)
db.write("I love coroutines!")
db.close()
}
delay(200.milliseconds)
dbTask.cancel()
}
println("I leaked a resource!")
}
Shows a coroutine that is cancelled before DatabaseConnection.close() runs, leaving the resource leaked. section 15.2.8
Prevent leaks by making cleanup execute even when cancellation interrupts normal work:
- Put resource use inside a finally block; cancellation raises CancellationException, but finally still runs. section 15.2.8
- Use the .use function for resources implementing AutoCloseable; it provides an idiomatic automatic-close shorthand. section 15.2.8
- Keep concurrent work structured so operations are awaited or cancelled instead of being launched and forgotten. section 14.3
Listing 15.6 Using a finally block to close resources
val dbTask = launch {
val db = DatabaseConnection()
try {
delay(500.milliseconds)
db.write("I love coroutines!")
} finally {
db.close()
}
}
Demonstrates explicit cleanup with finally around cancellable database work. section 15.2.8
Listing 15.7 Using use to automatically close resources
val dbTask = launch {
DatabaseConnection().use {
delay(500.milliseconds)
it.write("I love coroutines!")
}
}
Demonstrates automatic cleanup with use around the same cancellable database operation. section 15.2.8


