Dalvik: qué es, máquina virtual y cómo funciona

Autor: IT Sectr Publicado: 2026-04-16 Tiempo de lectura: 9 min

La máquina virtual Dalvik fue un componente clave del sistema operativo Android, responsable de ejecutar aplicaciones hasta la versión 4.4 KitKat. Desarrollada por Dan Bornstein, esta VM basada en registros reemplazó el concepto de JVM estándar y permitió optimizar el inicio de aplicaciones en dispositivos móviles con RAM limitada. Según Google, 2024, Dalvik garantizaba la compatibilidad de aplicaciones mediante compilación JIT, convirtiendo el bytecode DEX en instrucciones de máquina directamente durante la ejecución.

Puntos clave

  • Dalvik es una máquina virtual con arquitectura de registros, optimizada para Android.
  • A diferencia de la JVM, Dalvik ejecuta bytecode DEX, especialmente comprimido para dispositivos móviles.
  • La compilación JIT convierte parte del código DEX en código máquina directamente mientras la aplicación se ejecuta.
  • A partir de Android 5.0, Dalvik fue reemplazada por ART con compilación AOT anticipada.
  • Comprender Dalvik es necesario para admitir versiones antiguas de Android y analizar la compatibilidad retrospectiva.

¿Qué es Dalvik?

Dalvik es una máquina virtual con arquitectura de registros, creada específicamente para la plataforma Android. El desarrollo comenzó en 2005 por la empresa de Dan Bornstein, y en 2007 el proyecto fue adquirido por Google. La primera versión comercial de Dalvik apareció con el lanzamiento de Android 1.0 en 2008.

A diferencia de la Máquina Virtual de Java estándar (JVM), Dalvik no ejecuta bytecode de Java. El compilador de Java convierte el código fuente en archivos class, y luego la utilidad dx los traduce al formato Dalvik Executable (DEX). Este formato es más compacto que los archivos class: una aplicación de 10 MB en formato class ocupa aproximadamente 6–7 MB en DEX.

Historia de creación

Dan Bornstein escribió Dalvik como un proyecto para sistemas operativos con recursos limitados. El nombre proviene de la aldea islandesa de Dalvík. Google eligió Dalvik en lugar de JVM debido a restricciones de licencia y la necesidad de optimización profunda para procesadores móviles con arquitectura ARM. El sistema rápidamente ganó popularidad: para 2012, más de 500 millones de dispositivos Android funcionaban con Dalvik.

Rol en el ecosistema Android

Cada aplicación de Android se ejecuta en un proceso separado con su propia instancia de la VM Dalvik. Esto garantiza el aislamiento de datos y la protección contra código malicioso a nivel del sistema operativo. Este enfoque combina las ventajas de la virtualización con el sandbox de Linux: el malware en una aplicación no puede afectar a procesos vecinos.

Arquitectura de Dalvik: máquina de registros y DEX

La arquitectura basada en registros de Dalvik difiere fundamentalmente de la arquitectura basada en pila de JVM. En lugar de operaciones en la cima de la pila, Dalvik opera con registros — celdas virtuales dentro de la VM. Cada instrucción contiene las direcciones de los registros operando, lo que reduce el número de instrucciones por operación.

La máquina de pila JVM utiliza instrucciones como push, pop y add — para sumar dos números se requieren tres instrucciones. Dalvik resuelve la misma tarea con una instrucción add-int con tres registros. Según el Android Open Source Project, la arquitectura de registros de DEX reduce el tamaño del bytecode en un promedio del 30% en comparación con el formato de pila class.

Formato DEX

Un archivo DEX (Dalvik Executable) contiene una representación comprimida de todas las clases de la aplicación. El encabezado del archivo incluye una suma de verificación, tamaños de sección y desplazamientos. Las secciones principales son los grupos de cadenas, tipos, prototipos de métodos, campos y el propio bytecode. Un solo archivo DEX puede almacenar hasta 65,536 métodos (la limitación se eliminó con la introducción de multi-dex en Android 5.0).

La utilidad dx, incluida en Android SDK Build Tools, se utiliza para convertir archivos class a DEX. Ejemplo de comando: dx --dex --output=classes.dex myapp.jar. Los proyectos modernos usan D8, el sucesor de dx con optimización mejorada y soporte para funciones de Java 8+.

bash
# Conversión de JAR a DEX usando dx
dx --dex --output=classes.dex myapp.jar

# Versión moderna mediante D8
d8 --lib android.jar --output dex/ myapp.jar

Zygote: precarga del framework

El proceso Zygote es un elemento crucial de la arquitectura Dalvik. Cuando el sistema se inicia, Zygote carga todas las clases del SDK de Android, abre bibliotecas compartidas y crea un grupo de recursos precargados. Cuando un usuario abre una aplicación, el sistema bifurca el proceso Zygote (fork), creando una nueva instancia de la VM Dalvik con un framework ya inicializado. Esto reduce el tiempo de inicio de la aplicación de ~2–3 segundos a 300–500 milisegundos.

Compilación JIT en Dalvik

JIT (Just-In-Time) es una tecnología para compilar bytecode en instrucciones de máquina directamente durante la ejecución de la aplicación. En Dalvik, el compilador JIT analiza el código DEX en ejecución, identifica métodos utilizados con frecuencia (hot) y los compila en código nativo para la CPU.

La elección de JIT en lugar de la compilación Ahead-Of-Time (AOT) completa en las primeras versiones de Android fue deliberada. Los dispositivos móviles tenían almacenamiento flash limitado (4–16 GB) — precompilar todas las aplicaciones habría ocupado un espacio significativo. Adicionalmente, la memoria ROM en los primeros dispositivos era más lenta que la RAM, y leer código precompilado podía reducir el rendimiento.

Proceso de compilación JIT

Cuando una aplicación se inicia, Dalvik comienza a interpretar el bytecode DEX. Un perfilador especial rastrea qué métodos se llaman con más frecuencia. Después de superar un umbral (típicamente ~200 llamadas), el compilador JIT convierte el método en código máquina y lo almacena en caché en la RAM. Las llamadas posteriores utilizan la versión ya compilada sin necesidad de recompilación.

java
// Ejemplo de un método hot que JIT compilará
public class Calculator {
    public int sumArray(int[] arr) {
        int total = 0;
        for (int i = 0; i < arr.length; i++) {
            total += arr[i];
        }
        return total;
    }
}

Rendimiento de JIT

Según Google I/O 2013, la introducción de JIT en Android 2.2 Froyo aceleró la ejecución de aplicaciones en un promedio de 2–5 veces en comparación con la interpretación pura. Sin embargo, JIT añade latencia en el primer inicio: una aplicación necesita de 3 a 10 segundos para calentar y compilar métodos hot. Después del calentamiento, el rendimiento se estabiliza a un nivel cercano al código nativo.

Dalvik vs JVM: diferencias clave

Dalvik difiere de JVM en varios aspectos fundamentales. Primero — arquitectura: JVM está basada en pila, Dalvik en registros. Segundo — formato de bytecode: JVM usa archivos class, Dalvik usa DEX. Tercero — gestión de memoria: Dalvik está optimizada para la RAM limitada de dispositivos móviles.

Ambos enfoques tienen sus puntos fuertes. La JVM basada en pila requiere menos espacio para almacenar instrucciones — cada instrucción es más corta porque los operandos se toman implícitamente de la pila. Dalvik basada en registros ejecuta menos instrucciones por operación, lo que ahorra tiempo de CPU y reduce el consumo de energía. Para dispositivos móviles con batería, esto es crítico.

ParámetroDalvikJVM
ArquitecturaBasada en registrosBasada en pila
BytecodeDEXclass
CompilaciónJIT (Android 2.2+)JIT / AOT
OptimizaciónBajo consumo de energíaAlta compatibilidad
AislamientoMediante procesos LinuxMediante ClassLoader

Aspectos de licencia

La elección de Dalvik sobre JVM también estuvo motivada por las licencias. Oracle posee los derechos de Java SE y JVM, y Google buscaba evitar pagos de licencias. Crear su propia VM con un formato de bytecode alternativo permitió a Android desarrollarse independientemente de Oracle. Esta disputa se convirtió en una larga batalla legal, Oracle vs Google (2010–2021), que terminó a favor de Google.

Formato DEX y la utilidad dx

DEX (Dalvik Executable) es un formato binario que contiene el código compilado de una aplicación Android. Cada archivo DEX comienza con un encabezado, seguido de secciones: constantes de cadena (string_ids), tipos (type_ids), prototipos de métodos (proto_ids), campos (field_ids), métodos (method_ids), definiciones de clases (class_defs) y un área de datos.

La utilidad dx convierte archivos class de Java en uno o más archivos DEX. El algoritmo incluye deduplicación de constantes — las cadenas o tipos idénticos se almacenan una vez y se referencian por índice. Esto reduce significativamente el tamaño final. En proyectos modernos, dx ha sido reemplazado por D8 (introducido en Android Studio 3.1), que es 2–3 veces más rápido y admite desugaring de Java 8.

java
// Ejemplo de bytecode DEX descompilado mediante dexdump
// Código fuente: return a + b;
@Ldalvik/annotation/Code;
    registers: 3
    add-int v0, v1, v2
    return v0

Multi-dex: superando el límite de 65536

La limitación del formato DEX de 65,536 métodos (límite de índice de 16 bits) se convirtió en un problema serio para aplicaciones grandes. La solución llegó con Android 5.0: el soporte multi-dex permite que una aplicación contenga múltiples archivos DEX. El archivo principal classes.dex contiene los puntos de entrada, mientras que classes2.dex, classes3.dex adicionales, y así sucesivamente, contienen el resto del código. La configuración multi-dex se habilita en build.gradle con la línea multiDexEnabled true.

Gestión de memoria y recolección de basura

La recolección de basura en Dalvik se implementa como un recolector generacional con marcado y barrido (mark-and-sweep). La memoria se divide en dos áreas principales: Heap (montón) para objetos y Stack (pila) para primitivas y referencias. Cuando el Heap se llena, Dalvik suspende todos los hilos (STW — Stop-The-World), marca los objetos alcanzables y libera los inalcanzables.

Antes de Android 2.2, Dalvik usaba un recolector de un solo hilo con duraciones de pausa de hasta 100–200 ms. Android 2.3 Gingerbread introdujo un recolector concurrente que redujo las pausas típicas a 5–10 ms. Y Android 4.0 Ice Cream Sandwich agregó un recolector con limpieza incremental — Concurrent Mark and Sweep (CMS).

Fugas de memoria

Un problema típico de las aplicaciones Dalvik son las fugas de memoria a través de referencias estáticas a Activity. Si un campo estático mantiene una referencia a Context o View, el recolector de basura no puede liberar la Activity incluso después de cerrar la pantalla. Herramientas como Eclipse MAT y LeakCanary ayudan a detectar tales fugas: analizan un volcado del Heap y muestran cadenas de referencias que mantienen el objeto.

java
// Ejemplo de fuga de memoria a través de una referencia estática
public class Utils {
    private static Context context;

    public static void init(Context ctx) {
        context = ctx; // Mantiene Activity después de finish()
    }
}

Limitaciones de Dalvik y transición a ART

A pesar de su éxito, Dalvik tenía varios inconvenientes. La compilación JIT requería tiempo de calentamiento — los primeros segundos de funcionamiento de la aplicación eran más lentos. Además, JIT consumía energía de la CPU durante la compilación, reduciendo la duración de la batería. A medida que crecía el rendimiento de los dispositivos móviles y aumentaba el almacenamiento incorporado, la necesidad de JIT disminuyó.

En Android 4.4 KitKat, Google presentó ART (Android Runtime) como reemplazo experimental de Dalvik. A partir de Android 5.0 Lollipop, ART se convirtió en el único entorno de ejecución. La principal diferencia es la compilación AOT: en lugar de compilar durante la ejecución, todas las aplicaciones se compilan en código máquina durante la instalación. Esto eliminó los retrasos de calentamiento y mejoró la eficiencia energética.

Compatibilidad retrospectiva

La transición de Dalvik a ART fue transparente para los desarrolladores: ambos entornos ejecutan el mismo bytecode DEX. Las aplicaciones compiladas para Dalvik funcionan en ART sin recompilación — system_server las compila en código nativo durante la instalación. La excepción es el código que utiliza reflexión para acceder a miembros internos de la VM Dalvik: dicho código podría romperse en ART debido a cambios en la arquitectura interna.

Preguntas frecuentes

¿Qué es Dalvik en términos simples?

Dalvik es un programa intermediario que ejecuta aplicaciones Android en un teléfono. Toma el código de la aplicación y lo convierte en comandos comprensibles para el procesador, haciéndolo directamente mientras el usuario trabaja.

¿En qué se diferencia Dalvik de JVM?

Dalvik utiliza una arquitectura basada en registros y el formato DEX, mientras que JVM utiliza una arquitectura basada en pila y el formato class. Dalvik está optimizada para dispositivos móviles con memoria y potencia de procesamiento limitadas, mientras que JVM está diseñada para computadoras de escritorio y servidores.

¿Por qué Google reemplazó Dalvik por ART?

ART proporciona un mayor rendimiento mediante la compilación AOT anticipada — la aplicación se compila una vez durante la instalación, no cada vez que se inicia. Esto acelera el funcionamiento y ahorra batería en comparación con el enfoque JIT de Dalvik.

¿Funcionan las aplicaciones antiguas en ART?

Sí, ART es completamente compatible con el bytecode DEX de Dalvik. Durante la instalación, ART compila los archivos DEX antiguos en código nativo. La excepción son las aplicaciones que usan reflexión para acceder a mecanismos internos de Dalvik.

¿Qué es un archivo DEX?

DEX (Dalvik Executable) es un formato de archivo ejecutable que contiene bytecode comprimido de una aplicación Android. Un solo APK puede contener múltiples archivos DEX (multi-dex) si la aplicación tiene más de 65,536 métodos.

Resumen

  • Dalvik VM es una máquina virtual basada en registros creada para Android y utilizada hasta la versión 4.4 KitKat.
  • El formato DEX proporciona almacenamiento compacto de bytecode — 30% más pequeño que los archivos class de JVM.
  • La compilación JIT en Dalvik aceleró la ejecución de aplicaciones entre 2 y 5 veces en comparación con la interpretación pura.
  • El proceso Zygote precarga el framework de Android, reduciendo el tiempo de inicio de aplicaciones a 300–500 ms.
  • El límite de 65,536 métodos en un solo archivo DEX se resuelve mediante multi-dex a partir de Android 5.0.
  • La recolección de basura en Dalvik evolucionó desde un STW de un solo hilo hasta Concurrent Mark and Sweep.
  • La transición a ART en Android 5.0 eliminó los retrasos de calentamiento de JIT y mejoró la eficiencia energética.

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.

Discutir el proyecto

Lea también