Android Runtime (ART) es el entorno de ejecución de aplicaciones Android, introducido en Android 5.0 Lollipop como reemplazo de Dalvik. La principal innovación es la compilación AOT (ahead-of-time) del código de bytes DEX en código máquina nativo directamente durante la instalación de la aplicación, eliminando el problema de larga data del calentamiento del compilador JIT. Según Google, 2024, ART proporciona un aumento de rendimiento del 20–30% en comparación con Dalvik, manteniendo la compatibilidad total con el formato DEX.
Puntos clave
Android Runtime (ART) es un entorno de ejecución de aplicaciones que compila el código de bytes DEX en código máquina nativo antes de la ejecución. A diferencia de Dalvik, que utilizaba compilación Just-In-Time durante la ejecución, ART realiza compilación Ahead-Of-Time (AOT) durante la instalación del APK. Este cambio arquitectónico fundamental condujo a una aceleración significativa de las aplicaciones y a un menor consumo de energía.
ART apareció por primera vez como una opción experimental en Android 4.4 KitKat. Los desarrolladores podían activarla en la configuración de desarrollador y probar sus aplicaciones. En Android 5.0 Lollipop, ART se convirtió en el entorno de ejecución predeterminado y Dalvik se eliminó por completo de la plataforma. Para cuando se lanzó Android 7.0 Nougat, ART recibió un modo de compilación híbrida.
La decisión de reemplazar Dalvik por ART no fue repentina. El trabajo en el nuevo entorno comenzó en 2012, cuando Google reconoció las limitaciones del enfoque JIT. Objetivos principales: acelerar el inicio de aplicaciones, reducir la carga de la CPU y disminuir el consumo de energía. El desarrollo fue liderado por el Android Runtime Group, que anteriormente trabajaba en optimizaciones de Dalvik.
ART utiliza la misma arquitectura basada en registros que Dalvik, pero con un compilador completamente rediseñado. En lugar de un intérprete y un compilador JIT, ART incluye el compilador AOT dex2oat, que convierte los archivos DEX en binarios ELF durante la instalación. Como resultado, las aplicaciones en ART se inician con rendimiento nativo de inmediato, sin fase de calentamiento.
ART conservó los principios clave de Dalvik: aislamiento de aplicaciones mediante procesos separados, arquitectura basada en registros y soporte del formato DEX. Sin embargo, la implementación interna se reescribió por completo. En lugar del intérprete de Dalvik, ART incluye tres modos de ejecución: intérprete, compilador JIT y compilador AOT dex2oat. La selección del modo depende de la etapa del ciclo de vida de la aplicación.
El componente clave de ART es dex2oat (dalvik executable to optimized android translator). Esta utilidad se ejecuta durante la instalación de la aplicación (desde Android 7.0, también durante la optimización en segundo plano). dex2oat lee los archivos DEX del APK, optimiza el código de bytes y genera un archivo OAT: un binario ELF con código nativo. Los archivos OAT se almacenan en el directorio /data/dalvik-cache/.
# Verificar archivos OAT en el dispositivo
adb shell ls -la /data/dalvik-cache/arm64/
# Recompilación forzada de la aplicación
adb shell cmd package compile -m speed com.example.app
El sistema ART consta de varios módulos interconectados. El compilador dex2oat se encarga de la generación de código nativo. El recolector de basura (GC) gestiona la liberación de memoria. El intérprete ejecuta código llamado con poca frecuencia sin compilación. El perfilador rastrea métodos activos para la compilación híbrida. Cada módulo puede funcionar de forma independiente, lo que hace que ART sea flexible y escalable.
A partir de Android 7.0 Nougat, ART utiliza un enfoque híbrido de compilación, combinando las ventajas de JIT y AOT. Durante la instalación de la aplicación, ART ya no realiza una compilación AOT completa; en su lugar, la aplicación se ejecuta en modo interpretado con compilación JIT de métodos activos. Esto reduce el tiempo de instalación y el espacio de almacenamiento.
Un perfilador en segundo plano funciona en paralelo. Recopila estadísticas de ejecución: qué métodos se llaman con más frecuencia, qué ramas de código se ejecutan, qué clases se cargan. Después de acumular suficientes datos (generalmente después de 2–3 ejecuciones de la aplicación), ART ejecuta dex2oat en segundo plano y compila solo los métodos activos perfilados en código nativo.
ART admite varios modos de compilación, gestionados a través de system_server. El modo “speed” compila todos los métodos con AOT (máximo rendimiento, instalación lenta). El modo “speed-profile” compila solo los métodos activos perfilados (equilibrio entre velocidad y tamaño). El modo “verify” solo verifica el código de bytes sin compilación (mínimo espacio, interpretación). Por defecto, se utiliza speed-profile, óptimo para la mayoría de las aplicaciones.
| Modo | Compilación | Tiempo de instalación | Rendimiento |
|---|---|---|---|
| speed | AOT completa | Lento | Máximo |
| speed-profile | AOT perfilada | Rápido | Alto |
| verify | Sin compilación | Instantáneo | Interpretación |
| space | AOT mínima | Medio | Medio |
El perfilador recopila datos de ejecución en archivos .prof especiales. Cada aplicación almacena su perfil en /data/misc/profiles/. Cuando se alcanza el umbral (generalmente 1000 muestras), el perfilador ejecuta dex2oat para compilar los métodos activos identificados. Los perfiles se conservan entre las actualizaciones de la aplicación, lo que acelera la reoptimización después de las actualizaciones OTA del sistema.
La recolección de basura en ART ha mejorado drásticamente en comparación con Dalvik. En lugar del Concurrent Mark and Sweep (CMS) de un solo hilo, ART utiliza un recolector generacional con varias optimizaciones: recolector móvil (compactación del montón), espacio de objetos grandes (almacenamiento separado para objetos grandes) y compactación concurrente (compactación paralela).
Una pausa típica de GC en ART es de 2–3 ms frente a 5–10 ms en Dalvik. Esto fue posible gracias a varios mecanismos. En primer lugar, ART utiliza read-barrier en lugar de stop-the-world para las fases concurrentes. En segundo lugar, el recolector generacional procesa solo la generación joven de objetos en la mayoría de los ciclos, sin tocar todo el montón. En tercer lugar, el espacio de objetos grandes (LOS) se asigna por separado y no participa en los ciclos regulares de GC.
// Habilitar registros de GC para depuración
System.logV("ART", "GC trigger: allocation failed");
// Llamada forzada a GC (no recomendada en producción)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Debug.getRuntimeIStats();
}
A pesar del GC mejorado, las fugas de memoria siguen siendo un problema relevante. Una causa específica de ART es la carga de bibliotecas nativas a través de JNI sin una liberación adecuada. Si el código nativo asigna memoria mediante malloc pero no llama a free, ART no puede liberar esta memoria, ya que está fuera del montón gestionado. La herramienta AddressSanitizer en Android NDK ayuda a identificar estas fugas.
ART y Dalvik son dos implementaciones fundamentalmente diferentes de la misma tarea: ejecutar aplicaciones Android. Las diferencias afectan a todos los niveles: desde la compilación hasta la gestión de la memoria. A continuación se presenta una comparación de los parámetros clave de rendimiento y compatibilidad.
La principal ventaja de ART es la eliminación del calentamiento de JIT. En Dalvik, una aplicación podía ralentizarse durante los primeros 3–10 segundos mientras JIT compilaba los métodos activos. En ART, todos los métodos ya están compilados en código nativo (o se compilarán en segundo plano). Esto es especialmente notable en juegos y aplicaciones con interfaz pesada: la diferencia de fps puede alcanzar el 15–20% a favor de ART.
| Parámetro | Dalvik | ART |
|---|---|---|
| Compilación | JIT (durante la ejecución) | AOT + híbrida (en la instalación) |
| Tiempo de inicio | 3–10 s (calentamiento) | Instantáneo |
| Tamaño del APK | ~6–7 MB (DEX) | +20% (OAT) |
| Pausas de GC | 5–10 ms | 2–3 ms |
| Consumo de energía | Mayor (JIT calienta la CPU) | Menor (código nativo) |
Todas las aplicaciones escritas para Dalvik funcionan en ART sin cambios. Google garantiza la compatibilidad total hacia atrás a nivel de código de bytes DEX. La excepción es el código que utiliza la API interna específica de Dalvik mediante reflexión: miembros de la clase dalvik.system.DexFile marcados con @hide en Android SDK. Dicho código debe actualizarse para usar API públicas.
ART se convirtió en el primer entorno de ejecución de Android con soporte nativo de funciones de Java 8. A partir de Android 7.0, ART incluye desugaring: el proceso de convertir construcciones de Java 8 (lambdas, referencias a métodos, Stream API) en código Java 7 equivalente. Esto permite usar sintaxis moderna sin perder compatibilidad con dispositivos antiguos.
El desugaring lo realiza el compilador D8 y funciona de la siguiente manera. El código fuente con una lambda se convierte en un método sintético dentro de la misma clase, y la lambda se reemplaza con una llamada invoke-custom. El runtime de ART incluye soporte para la instrucción invoke-custom, añadida específicamente para Java 8. En dispositivos con Android 6.0 e inferiores, las lambdas se desugarcen en clases anónimas.
// Lambda de Java 8 — desugaring en ART
button.setOnClickListener(v -> handleClick(v));
// Después del desugaring (equivalente en Java 7)
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleClick(v);
}
});
No todas las funciones de Java 8 son compatibles con el desugaring. La API java.time (fechas y hora) solo está disponible a través de desugar_jdk_libs, una biblioteca adicional añadida en build.gradle. Stream API también requiere desugar_jdk_libs. java.util.function y Optional funcionan sin dependencias adicionales. El soporte completo de Java 8 está disponible en dispositivos con Android 8.0 y superior sin desugaring.
Aunque ART es compatible hacia atrás, algunas prácticas de optimización mejoran el rendimiento específicamente en este entorno. La recomendación principal es minimizar la reflexión. ART compila los métodos visibles en tiempo de compilación en llamadas directas a código máquina. La reflexión obliga a ART a generar stubs adicionales, lo que ralentiza la ejecución entre un 10–15%.
A partir de Android 9.0, ART introdujo soporte para App Startup Optimization. El desarrollador puede marcar clases de inicialización en el manifiesto mediante <initialization>, y ART las precargará al iniciar la aplicación. Esto reduce el tiempo de inicio entre un 5–15% para aplicaciones con muchos plugins o bibliotecas.
<!-- App Startup Optimization en AndroidManifest.xml -->
<application>
<profileable
android:shell="true"
android:enable="true" />
</application>
Para medir el rendimiento en ART, use systrace y perfetto. Systrace muestra el tiempo de compilación de dex2oat, la frecuencia de GC y la velocidad de renderizado de fotogramas. Perfetto proporciona información más detallada: distribución de hilos, tiempo de transiciones JNI, carga de bibliotecas nativas. Ejecución: adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto -t 10s sched freq idle am wm.
Preguntas frecuentes
ART (Android Runtime) es el entorno de ejecución de aplicaciones Android que compila el código de la aplicación en código máquina durante la instalación. Esto acelera el inicio y el funcionamiento de las aplicaciones en comparación con el antiguo entorno Dalvik.
ART compila el código por adelantado (AOT) durante la instalación de la aplicación, mientras que Dalvik lo compilaba pieza por pieza durante la ejecución (JIT). Por lo tanto, en ART las aplicaciones se inician más rápido y consumen menos energía.
Ejecute adb shell getprop y busque la propiedad persist.sys.dalvik.vm.lib.2. El valor “libart.so” significa ART, “libdvm.so” significa Dalvik. Todos los dispositivos con Android 5.0+ usan ART como entorno de ejecución.
Mínimamente. La aplicación en sí permanece en formato APK con archivos DEX. ART crea un archivo OAT adicional en /data/dalvik-cache/, que ocupa entre un 10–20% más de espacio que el DEX original, pero este almacenamiento no se incluye en el tamaño del APK.
Sí, ART admite la mayoría de las funciones de Java 8 mediante el mecanismo de desugaring. Las lambdas, las referencias a métodos y las interfaces funcionales funcionan en todos los dispositivos con Android 5.0+. Stream API y java.time requieren la biblioteca desugar_jdk_libs.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también