DEX: qué es, estructura y principio de funcionamiento del bytecode

Autor: IT Sectr Publicado: 2026-04-15 Tiempo de lectura: 8 min

DEX (Dalvik Executable) es un formato de bytecode en el que se compila el código fuente de las aplicaciones de Android en Java y Kotlin. Los archivos DEX se ejecutan en la máquina virtual Dalvik (hasta Android 4.4) o en Android Runtime (ART, a partir de Android 5.0). Según Android Open Source Project, 2026, el formato DEX proporciona en promedio un 30% de representación de código más compacta en comparación con el bytecode estándar de JVM.

Puntos clave

  • DEX es un formato de bytecode para Android, ejecutado en Dalvik o ART.
  • Compacidad — DEX ocupa un 30% menos de espacio que el bytecode Java estándar.
  • Multidex — un mecanismo para evitar el límite de 65536 métodos en un solo archivo DEX.
  • ART — Android Runtime, que reemplazó a Dalvik, compila DEX a código nativo durante la instalación.
  • D8 — un compilador moderno de Java/Kotlin a DEX, que reemplazó a DX desde 2018.

Qué es DEX y para qué se necesita

DEX (Dalvik Executable) es un formato de bytecode diseñado específicamente para dispositivos móviles Android. A diferencia del bytecode Java estándar (archivos .class), DEX está optimizado para recursos limitados: menos memoria, menor tamaño y carga de clases más rápida.

De Java a DEX

El código fuente en Java o Kotlin se compila con javac/kotlinc en archivos .class estándar (bytecode Java). Luego, la herramienta d8 (o anteriormente dx) convierte .class en uno o más archivos DEX. Esta conversión no es un simple reempaquetado — d8 realiza optimizaciones: fusiona grupos de constantes, reescribe instrucciones en arquitectura de registros y elimina datos duplicados.

Características arquitectónicas

DEX utiliza una arquitectura basada en registros (a diferencia de la JVM basada en pila). Cada método tiene un número fijo de registros (hasta 65536). Las instrucciones DEX son más cortas — en promedio 2 bytes frente a 1–4 bytes en JVM. Esto produce un código más compacto: una aplicación típica se reduce de 10–15 MB de .class a 4–6 MB de .dex.

Estructura del archivo DEX: secciones y encabezado

Un archivo DEX tiene una estructura binaria estrictamente definida. Cada archivo comienza con un encabezado y contiene varias secciones que se referencian entre sí mediante desplazamientos.

SecciónPropósito
headerEncabezado: magic, suma de verificación, firma, tamaños y desplazamientos de secciones
string_idsTabla de cadenas: nombres de clases, métodos, campos
type_idsTipos: referencias a identificadores de cadena de tipos
proto_idsPrototipos de métodos: tipo de retorno y parámetros
field_idsCampos de clases: clase, tipo, nombre
method_idsMétodos: clase, prototipo, nombre
class_defsDefiniciones de clases: flags, superclase, interfaces, desplazamientos de datos
dataDatos reales: código de métodos, anotaciones, información de depuración

Encabezado DEX

El número mágico de DEX es `dex\n035\0` (versión 035). Otras versiones: 036, 037, 038 (para Android 8.0+). El encabezado tiene un tamaño de 0x70 bytes y contiene una suma de verificación SHA-1 y los desplazamientos de todas las secciones. La validación del encabezado es el primer paso al cargar un DEX en la máquina virtual.

Grupos de constantes

string_ids, type_ids, proto_ids, field_ids, method_ids — son tablas indexadas. En lugar de almacenar nombres completos en el código del método, se utiliza un índice de 4 bytes. Esta es una optimización clave: si una clase se menciona 100 veces, su nombre se almacena una vez en string_ids. dex2oat optimiza aún más estas tablas durante la compilación ART.

Proceso de compilación de Java y Kotlin a DEX

El proceso de convertir el código fuente en DEX consta de varias etapas. La cadena de herramientas moderna utiliza el compilador D8, que reemplazó a DX en 2018 con Android Gradle Plugin 3.2.

Etapa 1: Compilación a .class

javac (para Java) o kotlinc (para Kotlin) compilan el código fuente en archivos .class. Cada clase es un archivo .class separado en bytecode Java. En esta etapa se realizan la verificación de tipos, la generación de métodos puente y la inserción de constantes.

Etapa 2: Compilación D8

D8 toma todos los archivos .class y los transforma a bytecode DEX. D8 realiza varias optimizaciones: elimina argumentos de métodos no utilizados, fusiona grupos de constantes de diferentes archivos .class en un grupo global de DEX y convierte instrucciones de pila JVM en instrucciones de registro Dalvik.

kotlin
// Código fuente Kotlin
data class User(
    val name: String,
    val email: String
)

fun greet(user: User): String {
    return "Hello, ${user.name}!"
}

Después de la compilación D8, este código se convierte en instrucciones DEX compactas: const-string para cargar cadenas, iget-object para acceder al campo de un objeto, invoke-virtual para llamar a StringBuilder.append.

D8 vs DX

D8 es 2–3 veces más rápido que DX, genera DEX más compacto (5–10% más pequeño) y optimiza mejor las construcciones específicas de Kotlin (funciones inline, lambdas). DX fue declarado obsoleto en 2018 y eliminado de Android Gradle Plugin 8.0.

Dalvik vs ART: cómo cambió la ejecución de DEX

La ejecución del código DEX en Android ha pasado por dos etapas: la máquina virtual Dalvik original (Android 2.2–4.4) y Android Runtime ART (Android 5.0+). La diferencia en el enfoque de compilación es fundamental.

Dalvik VM: compilación JIT

Dalvik utilizaba compilación Just-In-Time (JIT): el bytecode DEX se interpretaba y los métodos llamados con frecuencia se compilaban a código nativo sobre la marcha. Ventaja — instalación rápida. Desventaja — inicio más lento y consumo constante de CPU para JIT.

ART: compilación AOT

ART (Android Runtime) compila DEX a código nativo durante la instalación de la aplicación mediante dex2oat. Este es un enfoque Ahead-Of-Time (AOT): la instalación es más lenta, pero el inicio es más rápido y el consumo de energía es menor. Desde Android 7.0, ART utiliza un enfoque híbrido — AOT + JIT + Profile Guided Optimization.

dex2oat: conversión durante la instalación

La herramienta dex2oat se ejecuta al instalar o actualizar una aplicación. Compila DEX en un archivo ELF con código nativo para la arquitectura del dispositivo. El resultado — archivos .oat y .art en el directorio /data/dalvik-cache/. Google mejora continuamente dex2oat: en Android 14 se añadieron optimizaciones para dispositivos plegables.

Multidex: superando el límite de 64K métodos

El límite de 65536 métodos por archivo DEX es un legado de la arquitectura Dalvik. El campo method_ids en el encabezado DEX ocupa 4 bytes, lo que da un máximo de 2^16 = 65536 referencias únicas. Las aplicaciones modernas con Google Play Services, Firebase y otros SDK superan fácilmente este límite.

Mecanismo Multidex

Multidex es un mecanismo para dividir el código en múltiples archivos DEX. El classes.dex principal contiene los puntos de entrada (clase Application, Activity principal), los demás son classes2.dex, classes3.dex, etc. Al iniciar, las clases de los DEX adicionales se cargan mediante DexClassLoader.

kotlin
// build.gradle.kts — habilitación de multidex
android {
    defaultConfig {
        multiDexEnabled = true
    }
}

// Clase Application con soporte multidex
class MyApp : Application() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

Problemas de Multidex

La carga de DEX adicionales durante el inicio de la aplicación puede causar ANR (Application Not Responding) en dispositivos con Android anterior a 5.0. Recomendación — usar multidex solo cuando sea necesario y minimizar las dependencias para no superar el límite.

Optimización de DEX: ProGuard, R8 y ofuscación

La optimización de DEX es un paso estándar en la compilación de una aplicación Android de lanzamiento. Las herramientas R8 y ProGuard reducen el tamaño del DEX, ofuscan el código y eliminan clases no utilizadas.

R8 vs ProGuard

R8 es el sucesor de ProGuard, integrado en Android Gradle Plugin desde 2019. R8 realiza la minimización, ofuscación y optimización en una sola pasada, mientras que ProGuard requería dos etapas: ProGuard → D8. ProGuard aún tiene soporte, pero Google recomienda R8 para proyectos nuevos.

R8 elimina clases, métodos y campos no utilizados, los renombra con nombres cortos (a, b, c), incorpora funciones inline y elimina código muerto. El resultado — el DEX se reduce en un 20–40% sin pérdida de funcionalidad.

Reglas de R8

La configuración de R8 se especifica en el archivo proguard-rules.pro. El desarrollador puede indicar qué clases no se pueden renombrar (por ejemplo, para reflexión o serialización Gson). Firebase y otros SDK proporcionan sus propias reglas en sus dependencias.

Descompilación de DEX: herramientas y protección

DEX se puede descompilar de vuelta a código Java. Esta es una cuestión clave de seguridad en las aplicaciones Android: sin ofuscación, el código se restaura a un nivel cercano al original.

Herramientas de descompilación

JADX es el descompilador de DEX a Java más popular. Restaura nombres de clases, métodos, campos y la mayor parte de la lógica. apktool descompila DEX a código smali (ensamblador Dalvik) — una representación de bajo nivel cercana a las instrucciones originales. Bytecode Viewer combina múltiples descompiladores en una interfaz.

Métodos de protección

La ofuscación con R8/ProGuard es la primera línea de defensa: los nombres de clases y métodos se vuelven ilegibles. DexGuard es una herramienta comercial con métodos adicionales: cifrado de cadenas, verificación de integridad, anti-manipulación. La ofuscación del flujo de control (O-LLVM) cambia la estructura del código manteniendo su funcionalidad, haciendo el análisis mucho más difícil.

Preguntas frecuentes

¿En qué se diferencia DEX del bytecode Java?

DEX utiliza una arquitectura basada en registros en lugar de la JVM basada en pila, tiene un formato más compacto (30% más pequeño), fusiona todos los .class en un solo archivo con un grupo de constantes único y utiliza índices de 16 bits en lugar de 8 bits.

¿Qué es smali?

Smali es un ensamblador de bytecode DEX. Cada instrucción DEX tiene una representación textual en formato smali. La herramienta baksmali convierte DEX a smali (desensamblado), y smali ensambla smali de vuelta a DEX.

¿Cómo verificar la cantidad de métodos en DEX?

La tarea Gradle countMethods o el plugin dex-method-counts muestran la cantidad de métodos en cada archivo DEX. El comando adb shell con dumpsys también muestra estadísticas de los DEX cargados para las aplicaciones instaladas.

¿Afecta la cantidad de DEX al rendimiento?

, en dispositivos con Android anterior a 8.0, múltiples DEX ralentizan el inicio de la aplicación porque cada archivo adicional se carga por separado. En ART con Android 8.0+, la diferencia es mínima gracias a la compilación dex2oat en un solo archivo .oat.

¿Se puede ejecutar DEX sin Android?

, existen proyectos como dexplorer e implementaciones JVM compatibles con Android que pueden ejecutar bytecode DEX fuera de Android. Sin embargo, la mayoría de los archivos DEX utilizan la API de Android, lo que los hace inadecuados para ejecutarse en una JVM estándar.

Resumen

  • DEX es un formato de bytecode de Android con arquitectura basada en registros y representación compacta del código.
  • Estructura incluye encabezado, tablas de identificadores y sección de datos con instrucciones.
  • Compilación a DEX se realiza mediante D8: .class → DEX con optimizaciones y fusión de grupos de constantes.
  • ART compila DEX a código nativo durante la instalación (AOT), acelerando el inicio de la aplicación.
  • Multidex resuelve el límite de 65536 métodos dividiendo en múltiples archivos DEX.
  • Optimización — R8 reduce DEX en 20–40%, ofusca nombres y elimina código muerto.
  • Protección — ofuscación con R8/ProGuard, DexGuard y O-LLVM previene la descompilación de DEX.

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