Android Missing Recycle

ID

kotlin.android_missing_recycle

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Efficiency

Language

Kotlin

Tags

CWE:401, android, efficiency

Description

Reports Kotlin local properties holding a recyclable Android resource (TypedArray, VelocityTracker, MotionEvent, Parcel) that are acquired via a factory call such as obtain() or obtainStyledAttributes() but never have recycle() invoked on the binding within the same function body. Failing to recycle leaks the underlying object pool entry back to the framework, increases GC pressure, and on some devices causes silent resource exhaustion.

Rationale

fun bad() {
    val vt = VelocityTracker.obtain()   // FLAW — never recycled
    vt.addMovement(null)
}

fun good() {
    val vt = VelocityTracker.obtain()
    vt.addMovement(null)
    vt.recycle()                         // OK — properly recycled
}

fun handoff(): VelocityTracker {
    val vt = VelocityTracker.obtain()
    return vt                            // OK — ownership transferred to caller
}

The rule deliberately stays silent when the binding escapes the function (returned, passed as an argument, or stored into a field), because the receiver may be responsible for recycling.

Remediation

  • Wrap the work in try/finally and call recycle() in the finally block.

  • If the resource is handed off to another method or stored into a field, document the ownership transfer in the API.

  • For TypedArray obtained from obtainStyledAttributes, prefer Kotlin’s context.obtainStyledAttributes(…​).use { …​ } extension which auto-recycles.