How to Force ART Ahead-of-Time (AOT) App Compilation on Android Using ADB

In modern Android architecture, application runtime execution is managed by the Android Runtime (ART). Rather than relying entirely on Just-In-Time (JIT) interpretation or full static Ahead-Of-Time (AOT) binary compilation at install time, ART uses a hybrid profile-guided compilation model. When an app is freshly installed, it runs primarily via JIT interpretation. Over time, as the user interacts with the app, ART records hot code paths into a profile file. When the device is later connected to power and idle overnight, a background maintenance service compiles those hot methods into native machine code (OAT/ELF binaries).

While this adaptive model balances app install speed and disk footprint for consumer devices, it introduces significant variability when benchmarking app startup latency, CPU consumption, and frame rendering. For developers, QA engineers, and automated performance testing pipelines, waiting for background maintenance tasks is impractical. By leveraging the Android Debug Bridge (ADB) to interface with the cmd package compile command, you can force immediate AOT compilation, clear compilation caches, and audit DEX optimization states on demand.

Understanding Android Runtime Compilation Filters

ART supports several distinct compilation filters (specified by the -m flag), each representing a different trade-off between compilation time, disk storage usage, and runtime execution speed:

  • verify: Runs only DEX bytecode verification without compiling any native machine code. Execution relies entirely on JIT interpretation.
  • quicken: Performs bytecode verification and optimizes certain DEX opcodes for faster interpreter execution.
  • speed-profile: The production default on consumer handsets. Compiles only the methods and classes listed in the application’s runtime profile (hot code paths).
  • speed: Maximum Ahead-Of-Time compilation. Compiles all methods within the entire application package into native machine code. This produces the fastest possible runtime execution and eliminates JIT compilation pauses at the cost of larger disk usage and longer compilation time.
  • everything: Compiles everything, including rarely called error-handling code and unused library paths. Generally used only for compiler stress-testing.

Prerequisites and ADB Connectivity

Ensure that your target Android device or emulator has Developer Options and USB Debugging enabled. Verify device communication from your workstation terminal:

adb devices

Identify the application package name you wish to compile (e.g., com.example.myapp).

Forcing Full AOT Compilation with the speed Filter

To compile all DEX code within an application into native machine code, execute the package manager compilation command with the -m speed and -f (force) flags:

adb shell cmd package compile -m speed -f com.example.myapp

The console displays the compilation status:

[status=ok] compile com.example.myapp

With this command completed, ART has written compiled machine code directly into the app’s OAT directory. When the app is launched, zero CPU cycles are wasted on JIT interpretation during initial activity rendering, providing a consistent baseline for startup latency benchmarks.

Compiling Based on Profile-Guided Optimization (speed-profile)

To test how the application performs after several days of real-world usage without waiting for system idle maintenance:

  1. Interact with the app on the device to generate runtime execution data.
  2. Instruct the package manager to dump the active profile from memory to disk:
    adb shell cmd package dump-profiles com.example.myapp
  3. Trigger profile-guided compilation using the newly written profile:
    adb shell cmd package compile -m speed-profile -f com.example.myapp

ART compiles only the code paths exercised during your test session, mimicking realistic consumer device performance.

Inspecting and Auditing Active Compilation Status

To verify the current compilation filter applied to an installed package and inspect compiled code sizes:

adb shell dumpsys package com.example.myapp | grep -A 10 "Dexopt state:"

The terminal returns structured compilation metadata:

Dexopt state:
  [com.example.myapp]
    path: /data/app/~~.../base.apk
      arm64: [status=speed] [reason=cmdline] [primary-abi]

The output explicitly confirms that the active status is speed and the compilation reason is cmdline.

Resetting App Compilation to Factory State

To evaluate cold launch times on a completely uncompiled build or return an app to its initial post-installation state:

adb shell cmd package compile --reset com.example.myapp

Alternatively, force the compilation filter back to pure verification:

adb shell cmd package compile -m verify -f com.example.myapp

All previously generated OAT machine code is purged from disk, forcing the Android runtime to execute the app via the JIT interpreter again.

Batch Compiling All Installed Applications

In automated testing labs where complete device stability and consistent frame rates across all system apps are required, batch compile the entire operating system:

adb shell cmd package compile -m speed -a

(The -a switch instructs ART to compile all installed system and user packages).

Controlling ART compilation via ADB gives developers and QA teams complete mastery over Android execution performance, eliminating unpredictable JIT compilation anomalies during benchmarking.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.