Dalvik: cos'è, macchina virtuale e come funziona

Autore: IT Sectr Pubblicato: 2026-04-16 Tempo di lettura: 9 min

La macchina virtuale Dalvik è stata un componente chiave del sistema operativo Android, responsabile dell'esecuzione delle applicazioni fino alla versione 4.4 KitKat. Sviluppata da Dan Bornstein, questa VM basata su registri ha sostituito il concetto di JVM standard e ha permesso di ottimizzare l'avvio delle applicazioni su dispositivi mobili con RAM limitata. Secondo Google, 2024, Dalvik garantiva la compatibilità delle applicazioni attraverso la compilazione JIT, convertendo il bytecode DEX in istruzioni macchina direttamente durante l'esecuzione.

Punti chiave

  • Dalvik è una macchina virtuale con architettura a registri, ottimizzata per Android.
  • A differenza della JVM, Dalvik esegue bytecode DEX, appositamente compresso per dispositivi mobili.
  • La compilazione JIT converte parte del codice DEX in codice macchina direttamente mentre l'applicazione è in esecuzione.
  • A partire da Android 5.0, Dalvik è stata sostituita da ART con compilazione AOT anticipata.
  • Comprendere Dalvik è necessario per supportare vecchie versioni di Android e analizzare la compatibilità all'indietro.

Cos'è Dalvik?

Dalvik è una macchina virtuale con architettura a registri, creata specificamente per la piattaforma Android. Lo sviluppo iniziò nel 2005 dall'azienda di Dan Bornstein, e nel 2007 il progetto fu acquisito da Google. La prima versione commerciale di Dalvik apparve con il rilascio di Android 1.0 nel 2008.

A differenza della Macchina Virtuale Java standard (JVM), Dalvik non esegue bytecode Java. Il compilatore Java converte il codice sorgente in file class, e poi l'utilità dx li traduce nel formato Dalvik Executable (DEX). Questo formato è più compatto dei file class: un'applicazione di 10 MB in formato class occupa circa 6–7 MB in DEX.

Storia della creazione

Dan Bornstein scrisse Dalvik come progetto per sistemi operativi con risorse limitate. Il nome deriva dal villaggio islandese di Dalvík. Google scelse Dalvik invece di JVM a causa di restrizioni di licenza e della necessità di un'ottimizzazione profonda per processori mobili con architettura ARM. Il sistema guadagnò rapidamente popolarità: entro il 2012, oltre 500 milioni di dispositivi Android eseguivano Dalvik.

Ruolo nell'ecosistema Android

Ogni applicazione Android viene eseguita in un processo separato con la propria istanza della VM Dalvik. Ciò garantisce l'isolamento dei dati e la protezione contro il codice dannoso a livello di sistema operativo. Questo approccio combina i vantaggi della virtualizzazione con il sandbox Linux — il malware in un'applicazione non può influenzare i processi vicini.

Architettura di Dalvik: macchina a registri e DEX

L'architettura basata su registri di Dalvik differisce fondamentalmente dall'architettura basata su stack della JVM. Invece di operazioni sulla cima dello stack, Dalvik opera con registri — celle virtuali all'interno della VM. Ogni istruzione contiene gli indirizzi dei registri operandi, riducendo il numero di istruzioni per operazione.

La macchina a stack JVM utilizza istruzioni come push, pop e add — per sommare due numeri sono necessarie tre istruzioni. Dalvik risolve lo stesso compito con un'unica istruzione add-int con tre registri. Secondo Android Open Source Project, l'architettura a registri di DEX riduce la dimensione del bytecode in media del 30% rispetto al formato class basato su stack.

Formato DEX

Un file DEX (Dalvik Executable) contiene una rappresentazione compressa di tutte le classi dell'applicazione. L'intestazione del file include un checksum, le dimensioni delle sezioni e gli offset. Le sezioni principali sono i pool di stringhe, tipi, prototipi di metodi, campi e il bytecode stesso. Un singolo file DEX può memorizzare fino a 65.536 metodi (il limite è stato rimosso con l'introduzione del multi-dex in Android 5.0).

L'utilità dx, inclusa in Android SDK Build Tools, viene utilizzata per convertire i file class in DEX. Esempio di comando: dx --dex --output=classes.dex myapp.jar. I progetti moderni utilizzano D8, il successore di dx con ottimizzazione migliorata e supporto per le funzionalità Java 8+.

bash
# Conversione da JAR a DEX usando dx
dx --dex --output=classes.dex myapp.jar

# Versione moderna tramite D8
d8 --lib android.jar --output dex/ myapp.jar

Zygote: precaricamento del framework

Il processo Zygote è un elemento cruciale dell'architettura Dalvik. Quando il sistema si avvia, Zygote carica tutte le classi dell'SDK Android, apre le librerie condivise e crea un pool di risorse precaricate. Quando un utente apre un'applicazione, il sistema duplica il processo Zygote (fork), creando una nuova istanza della VM Dalvik con un framework già inizializzato. Ciò riduce il tempo di avvio dell'applicazione da ~2–3 secondi a 300–500 millisecondi.

Compilazione JIT in Dalvik

JIT (Just-In-Time) è una tecnologia per compilare bytecode in istruzioni macchina direttamente durante l'esecuzione dell'applicazione. In Dalvik, il compilatore JIT analizza il codice DEX in esecuzione, identifica i metodi frequentemente utilizzati (hot) e li compila in codice nativo per la CPU.

La scelta di JIT invece della compilazione completa Ahead-Of-Time (AOT) nelle prime versioni di Android è stata deliberata. I dispositivi mobili avevano memoria flash limitata (4–16 GB) — precompilare tutte le applicazioni avrebbe occupato spazio significativo. Inoltre, la memoria ROM nei primi dispositivi era più lenta della RAM, e leggere codice precompilato avrebbe potuto ridurre le prestazioni.

Processo di compilazione JIT

Quando un'applicazione viene avviata, Dalvik inizia a interpretare il bytecode DEX. Un profiler speciale tiene traccia di quali metodi vengono chiamati più frequentemente. Dopo aver superato una soglia (tipicamente ~200 chiamate), il compilatore JIT converte il metodo in codice macchina e lo memorizza nella cache in RAM. Le chiamate successive utilizzano la versione già compilata senza ricompilazione.

java
// Esempio di un metodo hot che JIT 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;
    }
}

Prestazioni di JIT

Secondo Google I/O 2013, l'introduzione di JIT in Android 2.2 Froyo ha accelerato l'esecuzione delle applicazioni in media di 2–5 volte rispetto all'interpretazione pura. Tuttavia, JIT aggiunge latenza al primo avvio: un'applicazione necessita di 3–10 secondi per riscaldarsi e compilare i metodi hot. Dopo il riscaldamento, le prestazioni si stabilizzano a un livello vicino al codice nativo.

Dalvik vs JVM: differenze principali

Dalvik differisce dalla JVM in diversi aspetti fondamentali. Primo — architettura: JVM è basata su stack, Dalvik è basata su registri. Secondo — formato del bytecode: JVM utilizza file class, Dalvik utilizza DEX. Terzo — gestione della memoria: Dalvik è ottimizzata per la RAM limitata dei dispositivi mobili.

Entrambi gli approcci hanno i loro punti di forza. La JVM basata su stack richiede meno spazio per memorizzare le istruzioni — ogni istruzione è più corta perché gli operandi vengono implicitamente presi dallo stack. Dalvik basata su registri esegue meno istruzioni per operazione, il che risparmia tempo CPU e riduce il consumo energetico. Per i dispositivi mobili alimentati a batteria, questo è fondamentale.

ParametroDalvikJVM
ArchitetturaBasata su registriBasata su stack
BytecodeDEXclass
CompilazioneJIT (Android 2.2+)JIT / AOT
OttimizzazioneBasso consumo energeticoAlta compatibilità
IsolamentoTramite processi LinuxTramite ClassLoader

Aspetti di licenza

La scelta di Dalvik anziché JVM è stata anche motivata dalle licenze. Oracle possiede i diritti su Java SE e JVM, e Google cercava di evitare le royalty. Creare una propria VM con un formato di bytecode alternativo ha permesso ad Android di svilupparsi indipendentemente da Oracle. Questa disputa si è trasformata in una lunga battaglia legale, Oracle contro Google (2010–2021), terminata a favore di Google.

Formato DEX e utilità dx

DEX (Dalvik Executable) è un formato binario contenente il codice compilato di un'applicazione Android. Ogni file DEX inizia con un'intestazione, seguita da sezioni: costanti di stringa (string_ids), tipi (type_ids), prototipi di metodi (proto_ids), campi (field_ids), metodi (method_ids), definizioni di classi (class_defs) e un'area dati.

L'utilità dx converte i file class Java in uno o più file DEX. L'algoritmo include la deduplicazione delle costanti — stringhe o tipi identici vengono memorizzati una volta e referenziati per indice. Ciò riduce significativamente la dimensione finale. Nei progetti moderni, dx è stato sostituito da D8 (introdotto in Android Studio 3.1), che è 2–3 volte più veloce e supporta il desugaring di Java 8.

java
// Esempio di bytecode DEX decompilato tramite dexdump
// Codice sorgente: return a + b;
@Ldalvik/annotation/Code;
    registers: 3
    add-int v0, v1, v2
    return v0

Multi-dex: superare il limite di 65536

La limitazione del formato DEX a 65.536 metodi (limite dell'indice a 16 bit) è diventata un serio problema per le applicazioni di grandi dimensioni. La soluzione è arrivata con Android 5.0: il supporto multi-dex consente a un'applicazione di contenere più file DEX. Il file principale classes.dex contiene i punti di ingresso, mentre i file aggiuntivi classes2.dex, classes3.dex e così via contengono il resto del codice. La configurazione multi-dex viene abilitata in build.gradle con la riga multiDexEnabled true.

Gestione della memoria e garbage collection

La garbage collection in Dalvik è implementata come un collector generazionale con mark-and-sweep. La memoria è divisa in due aree principali: Heap (mucchio) per gli oggetti e Stack (pila) per i primitivi e i riferimenti. Quando l'Heap si riempie, Dalvik sospende tutti i thread (STW — Stop-The-World), marca gli oggetti raggiungibili e libera quelli irraggiungibili.

Prima di Android 2.2, Dalvik utilizzava un collector a thread singolo con durate di pausa fino a 100–200 ms. Android 2.3 Gingerbread ha introdotto un collector concorrente che ha ridotto le pause tipiche a 5–10 ms. E Android 4.0 Ice Cream Sandwich ha aggiunto un collector con pulizia incrementale — Concurrent Mark and Sweep (CMS).

Perdite di memoria

Un problema tipico delle applicazioni Dalvik sono le perdite di memoria attraverso riferimenti statici ad Activity. Se un campo statico mantiene un riferimento a Context o View, il garbage collector non può liberare l'Activity nemmeno dopo la chiusura dello schermo. Strumenti come Eclipse MAT e LeakCanary aiutano a rilevare tali perdite: analizzano un dump dell'Heap e mostrano le catene di riferimenti che trattengono l'oggetto.

java
// Esempio di perdita di memoria tramite riferimento statico
public class Utils {
    private static Context context;

    public static void init(Context ctx) {
        context = ctx; // Mantiene Activity dopo finish()
    }
}

Limitazioni di Dalvik e transizione ad ART

Nonostante il suo successo, Dalvik presentava diversi inconvenienti. La compilazione JIT richiedeva tempo di riscaldamento — i primi secondi di funzionamento dell'applicazione erano più lenti. Inoltre, JIT consumava energia della CPU durante la compilazione, riducendo la durata della batteria. Con l'aumento delle prestazioni dei dispositivi mobili e l'incremento della memoria integrata, la necessità di JIT è diminuita.

In Android 4.4 KitKat, Google ha presentato ART (Android Runtime) come sostituto sperimentale di Dalvik. A partire da Android 5.0 Lollipop, ART è diventato l'unico ambiente di esecuzione. La differenza principale è la compilazione AOT: invece di compilare durante l'esecuzione, tutte le applicazioni vengono compilate in codice macchina durante l'installazione. Ciò ha eliminato i ritardi di riscaldamento e migliorato l'efficienza energetica.

Compatibilità all'indietro

La transizione da Dalvik ad ART è stata trasparente per gli sviluppatori: entrambi gli ambienti di esecuzione eseguono lo stesso bytecode DEX. Le applicazioni compilate per Dalvik funzionano su ART senza ricompilazione — system_server le compila in codice nativo durante l'installazione. L'eccezione è il codice che utilizza la riflessione per accedere ai membri interni della VM Dalvik: tale codice potrebbe rompersi su ART a causa di cambiamenti nell'architettura interna.

Domande frequenti

Cos'è Dalvik in parole semplici?

Dalvik è un programma intermediario che esegue le applicazioni Android sul telefono. Prende il codice dell'applicazione e lo converte in comandi comprensibili dal processore, facendolo direttamente mentre l'utente lavora.

In cosa Dalvik differisce dalla JVM?

Dalvik utilizza un'architettura basata su registri e il formato DEX, mentre la JVM utilizza un'architettura basata su stack e il formato class. Dalvik è ottimizzata per dispositivi mobili con memoria e potenza di elaborazione limitate, mentre la JVM è progettata per computer desktop e server.

Perché Google ha sostituito Dalvik con ART?

ART offre prestazioni superiori grazie alla compilazione AOT anticipata — l'applicazione viene compilata una volta durante l'installazione, non ogni volta che viene avviata. Ciò accelera il funzionamento e risparmia batteria rispetto all'approccio JIT di Dalvik.

Le vecchie applicazioni funzionano su ART?

Sì, ART è completamente retrocompatibile con il bytecode DEX di Dalvik. Durante l'installazione, ART compila i vecchi file DEX in codice nativo. L'eccezione sono le applicazioni che utilizzano la riflessione per accedere ai meccanismi interni di Dalvik.

Cos'è un file DEX?

DEX (Dalvik Executable) è un formato di file eseguibile contenente bytecode compresso di un'applicazione Android. Un singolo APK può contenere più file DEX (multi-dex) se l'applicazione ha più di 65.536 metodi.

Riepilogo

  • Dalvik VM è una macchina virtuale basata su registri creata per Android e utilizzata fino alla versione 4.4 KitKat.
  • Il formato DEX fornisce un archivio compatto di bytecode — più piccolo del 30% rispetto ai file class della JVM.
  • La compilazione JIT in Dalvik ha accelerato l'esecuzione delle applicazioni di 2–5 volte rispetto all'interpretazione pura.
  • Il processo Zygote precarica il framework Android, riducendo il tempo di avvio delle applicazioni a 300–500 ms.
  • Il limite di 65.536 metodi in un singolo file DEX viene risolto tramite multi-dex a partire da Android 5.0.
  • La garbage collection in Dalvik si è evoluta dallo STW a thread singolo al Concurrent Mark and Sweep.
  • La transizione ad ART in Android 5.0 ha eliminato i ritardi di riscaldamento di JIT e migliorato l'efficienza energetica.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche