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/finallyand callrecycle()in thefinallyblock. -
If the resource is handed off to another method or stored into a field, document the ownership transfer in the API.
-
For
TypedArrayobtained fromobtainStyledAttributes, prefer Kotlin’scontext.obtainStyledAttributes(…).use { … }extension which auto-recycles.