Virtuální stroj Dalvik — klíčová součást operačního systému Android, zodpovědná za spouštění aplikací až do verze 4.4 KitKat. Vyvinutá Danem Bornsteinem, registrová VM nahradila koncept standardní JVM a umožnila optimalizovat spouštění aplikací na mobilních zařízeních s omezenou RAM. Podle Google, 2024, Dalvik zajišťoval kompatibilitu aplikací pomocí JIT-kompilace, převádějící DEX-bajtkód do strojových instrukcí přímo během provádění.
Hlavní body
Dalvik — virtuální stroj s registrovou architekturou, vytvořený speciálně pro platformu Android. Vývoj začal v roce 2005 ve společnosti Dana Bornsteina a v roce 2007 projekt odkoupila společnost Google. První komerční verze Dalvik se objevila spolu s vydáním Android 1.0 v roce 2008.
Na rozdíl od standardního Java Virtual Machine (JVM), Dalvik nespouští Java-bajtkód. Java kompilátor převádí zdrojový kód do class-souborů, a poté nástroj dx je překládá do formátu Dalvik Executable (DEX). Tento formát je kompaktnější než class-soubory: aplikace o velikosti 10 MB ve formátu class zabírá přibližně 6–7 MB v DEX.
Dan Bornstein napsal Dalvik jako projekt pro operační systémy s omezenými zdroji. Název je převzat z islandské vesnice Dalvík. Google zvolil Dalvik místo JVM kvůli licenčním omezením a potřebě hluboké optimalizace pro mobilní procesory s ARM architekturou. Systém rychle získal popularitu: do roku 2012 běželo na Dalvik více než 500 milionů zařízení s Androidem.
Každá aplikace pro Android běží v samostatném procesu s vlastní instancí Dalvik VM. To zajišťuje izolaci dat a ochranu před škodlivým kódem na úrovni operačního systému. Tento přístup kombinuje výhody virtualizace s Linuxovým sandboxem — malware v jedné aplikaci nemůže ovlivnit sousední procesy.
Registrová architektura Dalvik se zásadně liší od zásobníkové architektury JVM. Místo operací s vrcholem zásobníku Dalvik pracuje s registry — virtuálními buňkami uvnitř VM. Každá instrukce obsahuje adresy registrů operandů, což snižuje počet instrukcí na jednu operaci.
Zásobníkový stroj JVM používá instrukce jako push, pop a add — pro sečtení dvou čísel jsou tři instrukce. Dalvik řeší stejný úkol jednou instrukcí add-int se třemi registry. Podle Android Open Source Project sníží registrová architektura DEX objem bajtkódu v průměru o 30% ve srovnání se zásobníkovým formátem class.
Soubor DEX (Dalvik Executable) obsahuje komprimované znázornění všech tříd aplikace. Hlavička souboru zahrnuje kontrolní součet, velikosti sekcí a posuny. Hlavní sekce jsou fondy řetězců, typů, prototypů metod, polí, metod a samotný bajtkód. V jednom DEX souboru lze uložit až 65536 metod (toto omezení bylo odstraněno zavedením multi-dex v Android 5.0).
Pro převod class-souborů do DEX se používá nástroj dx, který je součástí Android SDK Build Tools. Příklad příkazu: dx --dex --output=classes.dex myapp.jar. Moderní projekty používají D8 — nástupce dx s vylepšenou optimalizací a podporou funkcí Java 8+.
# Převod JAR do DEX pomocí dx
dx --dex --output=classes.dex myapp.jar
# Moderní verze přes D8
d8 --lib android.jar --output dex/ myapp.jar
Proces Zygote — nejdůležitější prvek architektury Dalvik. Při spuštění systému Zygote načítá všechny třídy Android SDK, otevírá sdílené knihovny a vytváří fond předběžně načtených zdrojů. Když uživatel otevře aplikaci, systém zkopíruje proces Zygote (fork), čímž vytvoří novou instanci Dalvik VM s již připraveným frameworkem. To zkracuje dobu spuštění aplikace z ~2–3 sekund na 300–500 milisekund.
JIT (Just-In-Time) — technologie kompilace bajtkódu do strojových instrukcí přímo během provádění aplikace. V Dalvik JIT kompilátor analyzuje prováděný DEX kód, identifikuje často používané (hot) metody a kompiluje je do nativního kódu pro CPU.
Výběr JIT místo úplné Ahead-Of-Time (AOT) kompilace v raných verzích Androidu byl vědomý. Mobilní zařízení měla omezenou flash paměť (4–16 GB) — předběžná kompilace všech aplikací by zabrala významné místo. Navíc ROM paměť v raných zařízeních pracovala pomaleji než RAM a čtení předem zkompilovaného kódu mohlo snížit výkon.
Když je aplikace spuštěna, Dalvik začne interpretovat DEX-bajtkód. Speciální profiler sleduje, které metody jsou volány nejčastěji. Po překročení prahu (obvykle ~200 volání) JIT kompilátor převede metodu na strojový kód a uloží jej do RAM. Následná volání používají již zkompilovanou verzi bez opětovné kompilace.
// Příklad hot metody, kterou JIT zkompiluje
public class Calculator {
public int sumArray(int[] arr) {
int total = 0;
for (int i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
}
}
Podle Google I/O 2013 implementace JIT v Android 2.2 Froyo zrychlila provádění aplikací v průměru 2–5krát ve srovnání s čistou interpretací. JIT však přidává zpoždění při prvním spuštění: aplikace potřebuje 3 až 10 sekund na zahřátí a kompilaci hot metod. Po zahřátí se výkon stabilizuje na úrovni blízké nativnímu kódu.
Dalvik se liší od JVM v několika zásadních parametrech. Zaprvé — architektura: JVM je zásobníková, Dalvik je registrová. Zadruhé — formát bajtkódu: JVM používá class-soubory, Dalvik používá DEX. Zatřetí — správa paměti: Dalvik je optimalizován pro omezenou RAM mobilních zařízení.
Oba přístupy mají silné stránky. Zásobníková JVM vyžaduje méně místa pro ukládání instrukcí — každá instrukce je kratší, protože operandy jsou implicitně brány ze zásobníku. Registrový Dalvik provádí méně instrukcí na jednu operaci, což šetří čas procesoru a snižuje spotřebu energie. Pro mobilní zařízení napájená z baterie je to kritické.
| Parametr | Dalvik | JVM |
|---|---|---|
| Architektura | Registrová | Zásobníková |
| Bajtkód | DEX | class |
| Kompilace | JIT (Android 2.2+) | JIT / AOT |
| Optimalizace | Nízká spotřeba energie | Vysoká kompatibilita |
| Izolace | Přes Linux procesy | Přes ClassLoader |
Výběr Dalvik místo JVM byl také dán licencováním. Oracle vlastní práva na Java SE a JVM a Google se snažil vyhnout licenčním poplatkům. Vytvoření vlastního VM s alternativním formátem bajtkódu umožnilo Androidu vyvíjet se nezávisle na Oracle. Tento spor vyústil v dlouholetý soudní proces Oracle vs Google (2010–2021), který skončil ve prospěch Google.
DEX (Dalvik Executable) — binární formát obsahující zkompilovaný kód aplikace pro Android. Každý DEX soubor začíná hlavičkou (header), za kterou následují sekce: řetězcové konstanty (string_ids), typy (type_ids), prototypy metod (proto_ids), pole (field_ids), metody (method_ids), definice tříd (class_defs) a datová oblast (data).
Nástroj dx převádí Java class-soubory do jednoho nebo více DEX souborů. Algoritmus práce zahrnuje deduplikaci konstant — stejné řetězce nebo typy jsou uloženy jednou a odkazovány pomocí indexu. To významně sníží výslednou velikost. V moderních projektech byl dx nahrazen D8 (objevil se v Android Studio 3.1), který je 2–3krát rychlejší a podporuje Java 8 desugaring.
// Příklad dekompilovaného DEX-bajtkódu přes dexdump
// Zdrojový kód: return a + b;
@Ldalvik/annotation/Code;
registers: 3
add-int v0, v1, v2
return v0
Omezení formátu DEX na 65536 metod (limit 16bitového indexu) se stalo vážným problémem pro velké aplikace. Řešení přišlo v Android 5.0: podpora multi-dex umožňuje aplikaci obsahovat více DEX souborů. Hlavní classes.dex obsahuje vstupní body a další classes2.dex, classes3.dex a tak dále obsahují zbývající kód. Konfigurace multi-dex se zapíná v build.gradle řádkem multiDexEnabled true.
Sběr odpadu v Dalvik je implementován jako generační (generational) sběrač s označováním a čištěním (mark-and-sweep). Paměť je rozdělena do dvou hlavních oblastí: Heap (halda) pro objekty a Stack (zásobník) pro primitivní typy a reference. Když se Heap zaplní, Dalvik pozastaví všechna vlákna (STW — Stop-The-World), označí dosažitelné objekty a uvolní nedosažitelné.
Až do Android 2.2 používal Dalvik jednovláknový sběrač s pauzami až 100–200 ms. V Android 2.3 Gingerbread se objevil souběžný sběrač, který snížil typické pauzy na 5–10 ms. A v Android 4.0 Ice Cream Sandwich přibyl sběrač s přírůstkovým čištěním — Concurrent Mark and Sweep (CMS).
Typický problém aplikací Dalvik — úniky paměti přes statické reference na Activity. Pokud statické pole ukládá referenci na Context nebo View, sběrač odpadu nemůže uvolnit Activity ani po zavření obrazovky. Nástroje jako Eclipse MAT a LeakCanary pomáhají odhalovat takové úniky: analyzují výsyp Heap a ukazují řetězce referencí držící objekt.
// Příklad úniku paměti přes statickou referenci
public class Utils {
private static Context context;
public static void init(Context ctx) {
context = ctx; // Drží Activity po finish()
}
}
Navzdory úspěchu měl Dalvik řadu nevýhod. JIT-kompilace vyžadovala čas na zahřátí — první sekundy provozu aplikace byly pomalejší. Kromě toho JIT spotřebovával energii procesoru během kompilace, což zkracovalo výdrž baterie. S rostoucím výkonem mobilních zařízení a zvětšující se kapacitou vestavěné paměti potřeba JIT klesla.
V Android 4.4 KitKat Google představil ART (Android Runtime) jako experimentální náhradu za Dalvik. Počínaje Androidem 5.0 Lollipop se ART stal jediným běhovým prostředím. Hlavní rozdíl — AOT kompilace: místo kompilace za běhu jsou všechny aplikace kompilovány do strojového kódu při instalaci. To odstranilo zpoždění zahřívání a zlepšilo energetickou účinnost.
Přechod z Dalvik na ART byl pro vývojáře transparentní: obě prostředí spouštějí stejný DEX-bajtkód. Aplikace vytvořené pro Dalvik běží na ART bez překompilování — system_server je kompiluje do nativního kódu při instalaci. Výjimkou je kód používající reflexi pro přístup k vnitřním členům Dalvik VM: takový kód se mohl na ART porouchat kvůli změně vnitřní architektury.
Často kladené otázky
Dalvik je zprostředkující program, který spouští aplikace pro Android v telefonu. Vezme kód aplikace a přemění jej na příkazy srozumitelné procesoru, a to přímo během práce uživatele.
Dalvik používá registrovou architekturu a formát DEX, zatímco JVM používá zásobníkovou architekturu a formát class. Dalvik je optimalizován pro mobilní zařízení s omezenou pamětí a procesorem, zatímco JVM je určena pro stolní počítače a servery.
ART poskytuje vyšší výkon díky předběžné AOT-kompilaci — aplikace se kompiluje jednou při instalaci, ne při každém spuštění. To zrychluje práci a šetří baterii ve srovnání s JIT přístupem Dalvik.
Ano, ART je plně zpětně kompatibilní s DEX-bajtkódem Dalvik. Při instalaci ART kompiluje staré DEX soubory do nativního kódu. Výjimkou jsou aplikace používající reflexi pro přístup k vnitřním mechanismům Dalvik.
DEX (Dalvik Executable) — formát spustitelného souboru obsahujícího komprimovaný bajtkód aplikace pro Android. V jednom APK může být více DEX souborů (multi-dex), pokud aplikace obsahuje více než 65536 metod.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také