tezvyn:

Explain generational GC in ART and why onDraw must avoid allocations

Curated by the Tezvyn teamSource: developer.android.comadvanced
Explain generational GC in ART and why onDraw must avoid allocations
WHAT IT TESTS

ART generational GC and onDraw allocation hazards.

ANSWER OUTLINE

Covers young-gen nursery, mark-sweep fallback, and why a 5-10ms GC pause misses 16ms frame deadline.

RED FLAG

Blaming GC without linking allocation to frame timing.

WHAT THIS TESTS: This question probes whether you understand ART's generational garbage collector and how it interacts with real-time UI rendering. The interviewer wants to see that you know memory allocation is not free on Android, that the UI thread has a hard 16.6 millisecond frame budget at 60 frames per second, and that custom drawing code is a common source of allocation-driven jank. It also tests whether you can distinguish between minor young-generation collections and full heap collections, and whether you understand that concurrent garbage collection still introduces pauses and CPU contention.

A GOOD ANSWER COVERS: First, explain that ART uses a generational heap with a young generation nursery for short-lived objects and an old generation for longer-lived data. Second, describe how minor GCs on the young generation are typically fast but are still stop-the-world events that pause all threads. Third, connect onDraw to frame timing: because onDraw is invoked every frame, even small allocations like new Rect or new Paint create a high-frequency garbage stream that rapidly fills the nursery, triggering repeated minor GCs or premature promotion to the old generation. Fourth, quantify the impact: a 5 to 10 millisecond GC pause directly consumes a third to two-thirds of the 16.6 millisecond frame budget, virtually guaranteeing a missed vsync and a dropped frame. Fifth, add nuance by noting that ART's concurrent GC reduces pause times but does not eliminate them, and that avoiding allocations in onDraw removes the root cause rather than relying on the collector to keep up.

COMMON WRONG ANSWERS: A major red flag is claiming that modern concurrent GC makes allocation-free drawing unnecessary. Another is jumping straight to object pooling without first explaining generational behavior or the frame budget. Some candidates blame GC generically without tying allocation rate to the 16.6 millisecond deadline, or assert that Kotlin's immutability makes zero allocation impossible, which ignores field-level reuse and canvas API design.

LIKELY FOLLOW-UPS: The interviewer may ask how you would profile this in production, which calls for Systrace or the Android Studio Memory Profiler to correlate GC events with frame drops. They might ask how this principle extends to RecyclerView binding or Compose recomposition. A deeper variant asks how object pools interact with generational collection, which touches on old-generation fragmentation and finalizers.

ONE CONCRETE EXAMPLE: Imagine a custom line chart that allocates a new Paint object inside onDraw for every grid line. At 60 frames per second with 10 lines, that is 600 Paint allocations every second. Each Paint holds native resources, so the young generation saturates within a few frames, causing a 3 to 5 millisecond minor GC pause every few hundred milliseconds. During a fling, stress promotes objects to the old generation, triggering a concurrent mark-sweep phase that stalls the UI thread for 15 milliseconds and drops two consecutive frames. The correct fix is to define the Paint as a final field, configure it once, and reuse it across draw calls, bringing allocations in onDraw to zero.

Source: developer.android.com

Read the original → developer.android.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.

Explain generational GC in ART and why onDraw must avoid allocations · Tezvyn