Mobile Development 15 min read

Understanding Dex2oat: Principles, Trigger Conditions, and Custom Optimization Strategies

This article explains the Dex2oat compilation process in Android, its various compiler filters, how to query and trigger optimizations in different scenarios such as boot, install, and idle, and presents custom strategies to improve performance while minimizing impact on user experience.

Coolpad Technology Team
Coolpad Technology Team
Coolpad Technology Team
Understanding Dex2oat: Principles, Trigger Conditions, and Custom Optimization Strategies

Dex2oat (Dalvik executable file to optimized ART file) is a program that compiles and optimizes DEX files, improving load speed, runtime performance, installation speed, startup time, and overall user experience.

Google's current Dex2oat mechanism has clear limitations: it consumes significant CPU resources during boot/OTA, can prolong first‑boot time when many APKs are scanned, and has strict idle‑trigger conditions that limit its effectiveness.

The article discusses the principles of Dex2oat and the thought process behind custom optimizations.

Basic Overview

An app’s Dex2oat optimization flow varies according to the selected compilation mode, which determines how many methods are optimized. The available compiler filters are defined by the following enum:

enum Filter {
  kAssumeVerified,      // Skip verification but mark all classes as verified anyway.
  kExtract,              // Delay verification to runtime, do not compile anything.
  kVerify,               // Only verify classes.
  kSpaceProfile,         // Maximize space savings based on profile.
  kSpace,                // Maximize space savings.
  kSpeedProfile,         // Maximize runtime performance based on profile.
  kSpeed,                // Maximize runtime performance.
  kEverythingProfile,    // Compile everything capable of being compiled based on profile.
  kEverything,           // Compile everything capable of being compiled.
};

Deeper filters provide greater optimization at the cost of more time and space.

To view the default compilation mode for different scenarios, run:

adb shell getprop |grep pm.dex
[pm.dexopt.ab-ota]: [speed-profile]
[pm.dexopt.bg-dexopt]: [speed-profile]
[pm.dexopt.boot]: [verify]
[pm.dexopt.first-boot]: [quicken]
[pm.dexopt.inactive]: [verify]
[pm.dexopt.install]: [speed-profile]
[pm.dexopt.shared]: [speed]

Dex2oat Trigger Timing

Dex2oat can be triggered in three main situations:

First boot : During boot, PMS scans installed packages and runs Dex2oat; many apps or slow Dex2oat can extend boot time.

App install/startup : PMS initiates Dex2oat when an app is installed or launched.

System idle : When the device is idle (e.g., charging) and certain conditions are met, Dex2oat runs in the background.

Since Android 10, apps can no longer trigger Dex2oat themselves, though work‑arounds exist by sending commands to the system.

The idle condition is defined in config_jobSchedulerInactivityIdleThreshold (31 minutes of inactivity) and differs from Doze idle.

Dex2oat Mechanism (Idle Scenario)

BackgroundDexOptService schedules a daily job that requires device idle, charging, and runs once per day. When the job starts, it checks storage, gathers optimizable packages, and decides the compilation reason.

js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
            .setRequiresDeviceIdle(true)
            .setRequiresCharging(true)
            .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
            .build());

The core optimization flow involves:

Resolving the real compiler filter for each package ( getRealCompilerFilter ).

Analyzing profile updates ( analyseProfiles ).

Performing the actual dex optimization ( dexOptPath ), which eventually calls the native dexopt.cpp binary.

Key native steps include opening the DEX file, creating the OAT output, and invoking the dex2oat binary:

UniqueFile in_dex(open(dex_path, O_RDONLY, 0), dex_path);
if (in_dex.fd() < 0) { /* error handling */ }
RestorableFile out_oat = open_oat_out_file(...);
if (out_oat.fd() < 0) { /* error handling */ }
bool use_dex2oat64 = false;
if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
  use_dex2oat64 = GetBoolProperty("dalvik.vm.dex2oat64.enabled", false);
}
const char* dex2oat_bin = select_execution_binary(
    use_dex2oat64 ? kDex2oat64Path : kDex2oat32Path,
    use_dex2oat64 ? kDex2oatDebug64Path : kDex2oatDebug32Path,
    background_job_compile);
RunDex2Oat runner(dex2oat_bin, execv_helper.get());
runner.Initialize(...);

After the optimization, logs such as the following can be used to measure duration and thread usage:

LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_)
          << " (" << PrettyDuration(ProcessCpuNanoTime() - start_cputime_ns_) << " cpu)"
          << " (threads: " << thread_count_ << ") ";

Factors Affecting Dex2oat Execution Time

Workload : Larger DEX files and higher compiler filters increase processing time.

Thread count : More threads reduce wall‑clock time but increase CPU contention.

eMMC performance : Heavy I/O and swapping can become bottlenecks.

System load : High overall load limits available CPU for Dex2oat.

Memory pressure : Low memory can cause I/O spikes and slowdowns.

Custom Dex2oat Optimization Strategies

Proposed customizations include:

Periodic background optimization for frequently used apps and small DEX files under idle + charging conditions.

Delay boot‑time Dex2oat for high‑frequency apps until after the system has settled.

Dynamically adjust CPU allocation and compiler filter based on current system load.

Testing with high‑speed cameras shows roughly a 15 % performance gain and reduced frame drops after applying these optimizations.

Baseline Profile Extension

Android 9 introduced ART baseline profiles, which are generated at build time, shipped with the APK via Play Store, and applied on first install to provide immediate performance benefits with far less system overhead than full Dex2oat runs.

Conclusion

The goal of both Google’s default Dex2oat strategy and vendor‑specific customizations is to deliver the runtime performance advantages of native machine code while minimizing the impact of the optimization process on overall device responsiveness.

References: CSDN blog, Android developer documentation, and related WeChat articles.

mobile developmentAndroidDex2oatcompiler filtersidle optimizationruntime optimization
Coolpad Technology Team
Written by

Coolpad Technology Team

Committed to advancing technology and supporting innovators. The Coolpad Technology Team regularly shares forward‑looking insights, product updates, and tech news. Tech experts are welcome to join; everyone is invited to follow us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.