Interview QuestionPractical QuestionFollow-up Questions

Android Memory Management and Memory Leaks

skydovesJaewoong Eum (skydoves)||8 min read

Android Memory Management and Memory Leaks

Android manages memory through a garbage collection mechanism that automatically reclaims objects no longer referenced by the application. The Dalvik and ART runtimes track object reachability and free unreachable objects during GC cycles. However, automatic garbage collection does not prevent memory leaks. A leak occurs when an object that should be eligible for collection is kept alive by an unintended reference chain. Understanding how Android allocates, tracks, and reclaims memory is foundational to writing apps that perform well under constrained resources. By the end of this lesson, you will be able to:

  • Explain how Android's garbage collector determines which objects to reclaim.
  • Describe the role of the low memory killer in Android's process management.
  • Identify common sources of memory leaks in Android applications.
  • Apply lifecycle aware patterns and tools to detect and prevent leaks.

How Garbage Collection Works on Android

ART uses a generational garbage collector that divides the heap into regions based on object age. Newly allocated objects go into a young generation space. Objects that survive multiple GC cycles are promoted to an older generation. This design optimizes for the observation that most objects are short lived.

During a GC cycle, the collector starts from a set of root references (stack variables, static fields, JNI references) and traverses all reachable objects. Anything not reachable from these roots is eligible for collection. ART uses concurrent collection to minimize pause times, running most of the marking phase on a background thread while the application continues executing:

class ImageProcessor {
    fun processImage(bitmap: Bitmap): Bitmap {
        val tempBuffer = ByteArray(bitmap.byteCount)
        // tempBuffer becomes eligible for GC
        // after processImage returns
        return applyFilter(bitmap, tempBuffer)
    }
}

In this example, tempBuffer becomes unreachable after the method returns and will be collected in a future GC cycle.

The Low Memory Killer

Android runs multiple apps simultaneously, each in its own process. When available memory drops below certain thresholds, the low memory killer (LMK) terminates processes to free memory. Processes are ranked by importance:

  1. Foreground processes (currently visible activity) have the highest priority.
  2. Visible processes (partially visible activity) are next.
  3. Service processes come after.
  4. Cached (background) processes are terminated first.

The system also sends onTrimMemory() callbacks with different levels (TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_UI_HIDDEN, etc.) to give apps a chance to release caches and non-essential resources before the LMK terminates them.

This interview continues for subscribers

Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.

Become a Sponsor