Garbage Collection (GC): What It Is, Algorithms, and Garbage Collection in Mobile Development

Author: IT Sectr Published: 2026-03-29 Reading time: 10 min

Automatic memory management through garbage collection is a key mechanism of the Android platform, based on the ART virtual machine. According to Google Android Documentation, 2026, the garbage collector frees developers from manual memory management, automatically removing objects that are no longer referenced. Without GC, every object allocation would require an explicit call to free or delete, which is physically impossible in the Java ecosystem with millions of objects per second.

Key Takeaways

  • Garbage Collection — an automatic memory freeing mechanism by removing unused objects in Java and Android
  • Basic Algorithms — Mark-and-Sweep, Copying Collection, and Generational Collection determine collection efficiency
  • ART and Dalvik — two implementations of the Android virtual machine, where ART (Android Runtime) replaced Dalvik starting from Android 5.0
  • GC Pauses — application execution stops during collection — the main cause of jank and performance issues
  • GC Optimization — reducing allocations, using object pools, and choosing the right collection types reduce the load on the garbage collector

What Is Garbage Collection (GC)?

Garbage Collection (GC) is an automatic process of detecting and freeing memory occupied by objects that are no longer used by the program. In the context of mobile development, GC is used on the Android platform through the ART virtual machine, as well as in the standard Java Virtual Machine.

Unlike languages with manual memory management (C, C++), where the programmer must explicitly call free or delete, GC completely takes on the task of tracking object lifecycles. The developer creates new objects using the new operator, while the collector determines when an object becomes unreachable — meaning no active references remain to it.

The main metrics of GC efficiency are pause time and throughput. Pause is the period during which application execution is stopped for collection. In a mobile environment, pauses longer than 8–16 milliseconds are noticeable as dropped frames (jank).

According to Google I/O 2019, ART in Android 10 reduced typical GC pauses to 2–4 ms, which is 70% less compared to Dalvik in Android 4.4. Nevertheless, improper memory management — frequent object allocation in loops, creating temporary instances unnecessarily — remains the main cause of performance issues.

How the Garbage Collector Works: Basic Algorithms

All GC implementations in Java and Android are based on several fundamental algorithms that are combined to achieve a balance between pause time and collection thoroughness. Understanding these algorithms is essential for writing GC-friendly code.

Mark-and-Sweep

Mark-and-Sweep is the simplest algorithm, working in two stages. In the Mark phase, the collector traverses the object graph starting from root references (root set) — local variables, static fields, thread stacks. Each reachable object is marked with a live flag. In the Sweep phase, the collector goes through the entire heap and frees the memory of unmarked objects.

The drawback is memory fragmentation: after Sweep, free areas alternate with occupied ones, making it difficult to allocate large objects. In mobile scenarios, this is critical since the heap is typically small (64–512 MB on Android).

Copying Collection

Copying Collection divides the heap into two semi-spaces. Active objects are copied compactly from one semi-space to the other, without gaps. After copying, the old semi-space is entirely declared free. The algorithm completely eliminates fragmentation, but requires twice as much memory.

In mobile environments, Copying Collection is used by generational collectors for fast cleanup of young objects, which statistically die early (weak generational hypothesis).

Generational Collection

Generational Collection divides the heap into generations: Young Generation (young objects) and Old Generation (old objects that survived several collections). Young generation collection (Minor GC) is performed frequently and quickly, since most objects die young. Old generation collection (Major GC or Full GC) occurs less frequently but takes longer.

java
// Demonstration of generational GC: young objects die fast
void processItems(List<Item> items) {
    List<Result> results = new ArrayList<>();       // lives for the entire method
    for (Item item : items) {
        Result r = new Result(item.getValue());    // dies instantly
        if (r.isValid()) {
            process(r);                               // r becomes garbage
        }
    }
    saveResults(results);                             // results moves to Old Gen
}

In this example, Result objects are created inside a loop and immediately become garbage — they are ideal candidates for Young GC. The results object lives longer and migrates to Old Generation. Generation separation allows Minor GC to clear young objects in milliseconds without touching the old heap.

Garbage Collection in Android: ART and Dalvik

Android evolved from Dalvik VM to ART (Android Runtime), and the GC implementation is one of the key differences between them. Understanding the GC architecture in Android helps write code that minimizes pauses on real devices.

CharacteristicDalvik (up to 4.4)ART (5.0+)
GC TypeMark-and-Sweep with Concurrent MarkGenerational + Concurrent
Typical Pause10–30 ms2–4 ms
CompactionNo (fragmentation grows only)Yes (in background, without stopping the app)
AOT CompilationJIT (Just-In-Time)AOT + JIT (hybrid)

Dalvik GC

Dalvik used a combination of Mark-and-Sweep with a concurrent phase. Concurrent Mark allowed the application to continue working during the object graph traversal, but the Sweep phase required stopping all threads (Stop-The-World). On devices with small amounts of RAM (512 MB — 1 GB), pauses reached 30 ms, causing noticeable interface lag. Additionally, Dalvik did not compact the heap, so after prolonged operation, fragmentation grew, and allocating large objects (e.g., Bitmap) could throw an OutOfMemoryError even with sufficient total free memory.

ART GC

ART (Android Runtime) introduced a generational collector with concurrent compaction. The heap is divided into three regions: Young, Mature (analogous to Old Generation), and Large Object Space (for objects larger than 12 KB). Young Region collection happens in parallel without stopping threads in most cases. In Android 10+, Concurrent Copying was introduced — compaction runs in a background thread without Stop-The-World.

Thanks to ART’s architecture, typical GC pauses were reduced to 2–4 ms, and in scenarios with a predominance of young objects — to 0.5–1 ms. This allowed Android devices to maintain stable 60 FPS even during active memory operations.

Types of Garbage Collectors in Java

In the Java ecosystem, there are several GC implementations, each with its own performance profile. For Android development, the choice is limited to ART, but knowledge of Java GC is useful when writing server-side code for mobile applications and when developing with Kotlin Multiplatform.

Serial GC

Serial GC is a single-threaded collector with full application stop (Stop-The-World). Each Mark, Sweep, and Compact operation is performed by one thread. Performance is low — not used for mobile servers. Only suitable for small applications with a heap of up to 100 MB.

Parallel GC

Parallel GC (also known as Throughput Collector) uses multiple threads for all collection phases. It is oriented toward maximum throughput — minimizing the time spent on GC relative to application runtime. Enabled via the -XX:+UseParallelGC flag in JVM.

G1 GC

G1 (Garbage-First) GC is the default collector in Java 9+. The heap is divided into regions of 1–32 MB. G1 predicts pause time and strives to stay within a specified limit (default 200 ms). Priority: regions with the largest amount of garbage are cleaned first (hence the name). G1 is effective for servers with large heaps (4–64 GB) with predictable pauses.

java
// Enabling G1 GC with target pause of 100 ms
// java -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -jar app.jar

public class MemoryMonitor {
    private static final long THRESHOLD = 512 * 1024 * 1024; // 512 MB

    public void checkHeapUsage() {
        Runtime rt = Runtime.getRuntime();
        long used = rt.totalMemory() - rt.freeMemory();
        if (used > THRESHOLD) {
            System.out.println("Heap usage exceeded threshold: " + used);
            System.out.println("Consider reducing allocations");
        }
    }
}

Monitoring the heap via Runtime allows detecting memory leaks at an early stage. If used exceeds 80% of the maximum heap under stable operation — this is a signal of a possible leak or excessive application memory consumption.

GC Problems and Memory Optimization in Mobile Applications

Even modern ART GC does not solve all problems — improper memory usage remains the main cause of jank and ANR (Application Not Responding). Let’s look at the main scenarios and optimization methods.

GC Pauses and Jank

GC Pauses — application thread stops during collection. On screen, this manifests as dropped frames, when the time between two frames exceeds 16.6 ms (60 FPS). If GC lasts 30 ms, only one frame is drawn instead of two — the user sees interface stuttering.

The main causes of long pauses: a large number of live objects in Old Generation, heap fragmentation, frequent Full GC. Android Studio Profiler and systrace are used for diagnostics.

Reducing GC Load

The main rule of GC-friendly code is to minimize the number of allocated objects. Each new object requires not only memory allocation but also subsequent collection. Even if GC is fast, 1000 extra allocations per second result in 1000 checks for the collector.

  • Avoid creating objects in loops — move creation outside the loop, reuse local variables
  • Use object pools — for Bitmap, byte[] and other heavy structures, use Object Pool or RecyclerView.ViewHolder
  • Prefer primitives — int instead of Integer, float instead of Float avoid autoboxing
  • Use SparseArray — instead of HashMap<Integer, V>, Android SDK offers SparseArray, LongSparseArray that work with primitives
  • StringBuilder instead of concatenation — each string concatenation creates a new String object

Memory Leaks

A memory leak occurs when an object remains reachable even though it is no longer needed. GC cannot delete such an object, and memory is gradually exhausted. Typical causes: unregistered listeners, static references to Activity, anonymous classes capturing external context, and unclosed Cursor/InputStream.

java
// Memory leak: anonymous class holds reference to Activity
public void startTask() {
    new Thread(new Runnable() {                    // implicitly holds this (Activity)
        @Override
        public void run() {
            // long operation...
            System.out.println("Done");
        }
    }).start();
}

// Fix: static nested class + WeakReference
private static class TaskRunnable implements Runnable {
    private WeakReference<Activity> activityRef;

    TaskRunnable(Activity activity) {
        this.activityRef = new WeakReference<>(activity);
    }

    @Override
    public void run() {
        Activity act = activityRef.get();
        if (act != null) {
            // safe work with Activity
        }
    }
}

In this example, the anonymous Runnable captures an implicit reference to the Activity. While the thread is alive — the Activity cannot be collected by GC, even if the user has already closed the screen. The WeakReference + static class fix breaks this chain and allows the Activity to be reclaimed.

Frequently Asked Questions

How is GC in Android different from GC in Java?

GC in Android (ART) is a generational collector with concurrent compaction, optimized for mobile devices with limited memory. Java GC (G1, ZGC) are server-side collectors with large heaps and predictable pauses. ART GC does not use JVM flags — all tuning is done automatically at the OS level.

What is Stop-The-World in GC?

Stop-The-World is the moment when the collector pauses all application threads to safely traverse the object graph or free memory. The longer the STW, the more noticeable the jank. ART reduced typical STW time to 2–4 ms thanks to its generational architecture.

How to detect a memory leak in Android?

Use Android Studio Memory Profiler — it shows heap growth, allocation count, and allows taking Heap Dumps. For in-depth analysis, use LeakCanary — the library automatically detects leaks and shows the reference chain preventing GC collection.

When does Full GC occur and why is it dangerous?

Full GC is a complete collection of all heap generations, including Old Generation. In mobile applications, Full GC can last 50–200 ms, causing noticeable jank or ANR. Main causes: heap fragmentation, memory leaks, exceeding the Old Generation threshold.

How does Kotlin help avoid memory leaks?

Kotlin provides coroutines with structured concurrency — scope cancellation automatically cancels all child coroutines, preventing leaks. Kotlin also has the lazy delegate for lazy initialization and scope functions that reduce the number of temporary objects.

Summary

  • Garbage Collection — automatic memory management by removing unreachable objects, the foundation of Android Runtime
  • Mark-and-Sweep — basic algorithm with two-phase collection, suffers from heap fragmentation
  • Copying Collection — eliminates fragmentation by copying live objects into a compact semi-space
  • Generational GC — divides the heap into generations (Young/Old), speeding up collection of short-lived young objects
  • ART in Android — generational collector with concurrent compaction and 2–4 ms pauses, replacing Dalvik in Android 5.0
  • GC Optimization — reducing allocations, object pools, primitives instead of wrappers, and SparseArray instead of HashMap reduce collector load
  • Diagnostics — Android Studio Profiler, systrace, and LeakCanary are the main tools for identifying memory issues

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also