La machine virtuelle Dalvik était un composant clé du système d’exploitation Android, responsable de l’exécution des applications jusqu’à la version 4.4 KitKat. Développée par Dan Bornstein, cette VM basée sur des registres a remplacé le concept de JVM standard et a permis d’optimiser le lancement des applications sur les appareils mobiles avec une RAM limitée. Selon Google, 2024, Dalvik assurait la compatibilité des applications grâce à la compilation JIT, convertissant le bytecode DEX en instructions machine directement pendant l’exécution.
Points clés
Dalvik est une machine virtuelle à architecture de registres, créée spécifiquement pour la plateforme Android. Le développement a commencé en 2005 par la société de Dan Bornstein, et en 2007, le projet a été acquis par Google. La première version commerciale de Dalvik est apparue avec la sortie d’Android 1.0 en 2008.
Contrairement à la machine virtuelle Java standard (JVM), Dalvik n’exécute pas de bytecode Java. Le compilateur Java convertit le code source en fichiers class, puis l’utilitaire dx les traduit au format Dalvik Executable (DEX). Ce format est plus compact que les fichiers class : une application de 10 Mo au format class occupe environ 6–7 Mo en DEX.
Dan Bornstein a écrit Dalvik comme un projet pour les systèmes d’exploitation aux ressources limitées. Le nom vient du village islandais de Dalvík. Google a choisi Dalvik plutôt que JVM en raison des restrictions de licence et de la nécessité d’une optimisation approfondie pour les processeurs mobiles avec architecture ARM. Le système a rapidement gagné en popularité : en 2012, plus de 500 millions d’appareils Android fonctionnaient sous Dalvik.
Chaque application Android s’exécute dans un processus séparé avec sa propre instance de la VM Dalvik. Cela garantit l’isolation des données et la protection contre le code malveillant au niveau du système d’exploitation. Cette approche combine les avantages de la virtualisation avec le bac à sable Linux : un logiciel malveillant dans une application ne peut pas affecter les processus voisins.
L’architecture basée sur des registres de Dalvik diffère fondamentalement de l’architecture basée sur la pile de la JVM. Au lieu d’opérations sur le sommet de la pile, Dalvik travaille avec des registres — des cellules virtuelles à l’intérieur de la VM. Chaque instruction contient les adresses des registres opérandes, ce qui réduit le nombre d’instructions par opération.
La machine à pile JVM utilise des instructions comme push, pop et add — pour additionner deux nombres, trois instructions sont nécessaires. Dalvik résout la même tâche avec une seule instruction add-int avec trois registres. Selon Android Open Source Project, l’architecture à registres de DEX réduit la taille du bytecode en moyenne de 30 % par rapport au format class basé sur la pile.
Un fichier DEX (Dalvik Executable) contient une représentation compressée de toutes les classes de l’application. L’en-tête du fichier comprend une somme de contrôle, les tailles des sections et les décalages. Les sections principales sont les pools de chaînes, de types, de prototypes de méthodes, de champs et le bytecode lui-même. Un seul fichier DEX peut stocker jusqu’à 65 536 méthodes (la limitation a été levée avec l’introduction du multi-dex dans Android 5.0).
L’utilitaire dx, inclus dans Android SDK Build Tools, est utilisé pour convertir les fichiers class en DEX. Exemple de commande : dx --dex --output=classes.dex myapp.jar. Les projets modernes utilisent D8, le successeur de dx avec une optimisation améliorée et la prise en charge des fonctionnalités Java 8+.
# Conversion de JAR en DEX avec dx
dx --dex --output=classes.dex myapp.jar
# Version moderne via D8
d8 --lib android.jar --output dex/ myapp.jar
Le processus Zygote est un élément crucial de l’architecture Dalvik. Au démarrage du système, Zygote charge toutes les classes du SDK Android, ouvre les bibliothèques partagées et crée un pool de ressources préchargées. Lorsqu’un utilisateur ouvre une application, le système duplique le processus Zygote (fork), créant une nouvelle instance de la VM Dalvik avec un framework déjà initialisé. Cela réduit le temps de lancement de l’application d’environ 2–3 secondes à 300–500 millisecondes.
JIT (Just-In-Time) est une technologie de compilation du bytecode en instructions machine directement pendant l’exécution de l’application. Dans Dalvik, le compilateur JIT analyse le code DEX en cours d’exécution, identifie les méthodes fréquemment utilisées (chaudes) et les compile en code natif pour le CPU.
Le choix de JIT plutôt que de la compilation complète Ahead-Of-Time (AOT) dans les premières versions d’Android était délibéré. Les appareils mobiles disposaient d’un stockage flash limité (4–16 Go) — la précompilation de toutes les applications aurait pris beaucoup de place. De plus, la mémoire ROM des premiers appareils était plus lente que la RAM, et la lecture de code précompilé aurait pu réduire les performances.
Lorsqu’une application est lancée, Dalvik commence à interpréter le bytecode DEX. Un profileur spécial suit quelles méthodes sont appelées le plus fréquemment. Après avoir dépassé un seuil (généralement ~200 appels), le compilateur JIT convertit la méthode en code machine et la met en cache dans la RAM. Les appels ultérieurs utilisent la version déjà compilée sans recompilation.
// Exemple d’une méthode chaude que JIT va compiler
public class Calculator {
public int sumArray(int[] arr) {
int total = 0;
for (int i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
}
}
Selon Google I/O 2013, l’introduction de JIT dans Android 2.2 Froyo a accéléré l’exécution des applications en moyenne de 2 à 5 fois par rapport à l’interprétation pure. Cependant, JIT ajoute une latence au premier lancement : une application a besoin de 3 à 10 secondes pour chauffer et compiler les méthodes chaudes. Après le chauffage, les performances se stabilisent à un niveau proche du code natif.
Dalvik diffère de la JVM sur plusieurs aspects fondamentaux. Premièrement — l’architecture : la JVM est basée sur la pile, Dalvik sur les registres. Deuxièmement — le format du bytecode : la JVM utilise des fichiers class, Dalvik utilise DEX. Troisièmement — la gestion de la mémoire : Dalvik est optimisée pour la RAM limitée des appareils mobiles.
Les deux approches ont leurs points forts. La JVM basée sur la pile nécessite moins d’espace pour stocker les instructions — chaque instruction est plus courte car les opérandes sont implicitement extraits de la pile. Dalvik basée sur les registres exécute moins d’instructions par opération, ce qui économise du temps CPU et réduit la consommation d’énergie. Pour les appareils mobiles alimentés par batterie, c’est essentiel.
| Paramètre | Dalvik | JVM |
|---|---|---|
| Architecture | Basée sur registres | Basée sur pile |
| Bytecode | DEX | class |
| Compilation | JIT (Android 2.2+) | JIT / AOT |
| Optimisation | Faible consommation | Haute compatibilité |
| Isolation | Via processus Linux | Via ClassLoader |
Le choix de Dalvik plutôt que JVM était également motivé par les licences. Oracle possède les droits sur Java SE et la JVM, et Google cherchait à éviter les redevances. La création de sa propre VM avec un format de bytecode alternatif a permis à Android de se développer indépendamment d’Oracle. Ce litige a débouché sur une longue bataille judiciaire, Oracle contre Google (2010–2021), qui s’est terminée en faveur de Google.
DEX (Dalvik Executable) est un format binaire contenant le code compilé d’une application Android. Chaque fichier DEX commence par un en-tête, suivi de sections : constantes de chaînes (string_ids), types (type_ids), prototypes de méthodes (proto_ids), champs (field_ids), méthodes (method_ids), définitions de classes (class_defs) et une zone de données.
L’utilitaire dx convertit les fichiers class Java en un ou plusieurs fichiers DEX. L’algorithme inclut la déduplication de constantes — les chaînes ou types identiques sont stockés une fois et référencés par index. Cela réduit considérablement la taille finale. Dans les projets modernes, dx a été remplacé par D8 (introduit dans Android Studio 3.1), qui est 2 à 3 fois plus rapide et prend en charge le desugar Java 8.
// Exemple de bytecode DEX décompilé via dexdump
// Code source : return a + b;
@Ldalvik/annotation/Code;
registers: 3
add-int v0, v1, v2
return v0
La limitation du format DEX à 65 536 méthodes (limite d’index 16 bits) est devenue un sérieux problème pour les grandes applications. La solution est venue avec Android 5.0 : la prise en charge du multi-dex permet à une application de contenir plusieurs fichiers DEX. Le fichier principal classes.dex contient les points d’entrée, tandis que les fichiers supplémentaires classes2.dex, classes3.dex, etc., contiennent le reste du code. La configuration multi-dex est activée dans build.gradle avec la ligne multiDexEnabled true.
La collecte des déchets dans Dalvik est implémentée comme un collecteur générationnel avec marquage et balayage (mark-and-sweep). La mémoire est divisée en deux zones principales : le Heap (tas) pour les objets et la Stack (pile) pour les primitifs et les références. Lorsque le Heap se remplit, Dalvik suspend tous les threads (STW — Stop-The-World), marque les objets atteignables et libère les inatteignables.
Avant Android 2.2, Dalvik utilisait un collecteur mono-thread avec des durées de pause allant jusqu’à 100–200 ms. Android 2.3 Gingerbread a introduit un collecteur concurrent qui a réduit les pauses typiques à 5–10 ms. Et Android 4.0 Ice Cream Sandwich a ajouté un collecteur avec nettoyage incrémental — Concurrent Mark and Sweep (CMS).
Un problème typique des applications Dalvik sont les fuites de mémoire via des références statiques à Activity. Si un champ statique contient une référence à Context ou View, le collecteur de déchets ne peut pas libérer l’Activity, même après la fermeture de l’écran. Des outils comme Eclipse MAT et LeakCanary aident à détecter ces fuites : ils analysent un dump du Heap et montrent les chaînes de références qui retiennent l’objet.
// Exemple de fuite de mémoire via une référence statique
public class Utils {
private static Context context;
public static void init(Context ctx) {
context = ctx; // Maintient Activity après finish()
}
}
Malgré son succès, Dalvik présentait plusieurs inconvénients. La compilation JIT nécessitait un temps de chauffage — les premières secondes de fonctionnement de l’application étaient plus lentes. De plus, JIT consommait de l’énergie du CPU pendant la compilation, réduisant ainsi l’autonomie de la batterie. À mesure que les performances des appareils mobiles augmentaient et que le stockage intégré augmentait, le besoin de JIT a diminué.
Dans Android 4.4 KitKat, Google a présenté ART (Android Runtime) comme remplacement expérimental de Dalvik. À partir d’Android 5.0 Lollipop, ART est devenu le seul environnement d’exécution. La principale différence est la compilation AOT : au lieu de compiler pendant l’exécution, toutes les applications sont compilées en code machine lors de l’installation. Cela a éliminé les délais de chauffage et amélioré l’efficacité énergétique.
La transition de Dalvik vers ART a été transparente pour les développeurs : les deux environnements d’exécution exécutent le même bytecode DEX. Les applications compilées pour Dalvik fonctionnent sur ART sans recompilation — system_server les compile en code natif lors de l’installation. L’exception concerne le code qui utilise la réflexion pour accéder aux membres internes de la VM Dalvik : un tel code pourrait se briser sur ART en raison des changements dans l’architecture interne.
Questions fréquentes
Dalvik est un programme intermédiaire qui exécute les applications Android sur le téléphone. Il prend le code de l’application et le convertit en commandes compréhensibles par le processeur, le faisant directement pendant que l’utilisateur travaille.
Dalvik utilise une architecture basée sur les registres et le format DEX, tandis que la JVM utilise une architecture basée sur la pile et le format class. Dalvik est optimisé pour les appareils mobiles avec une mémoire et une puissance de traitement limitées, tandis que la JVM est conçue pour les ordinateurs de bureau et les serveurs.
ART offre de meilleures performances grâce à la compilation AOT anticipée — l’application est compilée une fois lors de l’installation, pas à chaque démarrage. Cela accélère le fonctionnement et économise la batterie par rapport à l’approche JIT de Dalvik.
Oui, ART est totalement rétrocompatible avec le bytecode DEX de Dalvik. Lors de l’installation, ART compile les anciens fichiers DEX en code natif. L’exception concerne les applications qui utilisent la réflexion pour accéder aux mécanismes internes de Dalvik.
DEX (Dalvik Executable) est un format de fichier exécutable contenant le bytecode compressé d’une application Android. Un seul APK peut contenir plusieurs fichiers DEX (multi-dex) si l’application comporte plus de 65 536 méthodes.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi