Виртуелна машина Dalvik — кључни компонент оперативног система Android, одговоран за извршавање апликација све до верзије 4.4 KitKat. Развијен од стране Дена Борнштајна, регистарска VM замијенила је концепт стандардне JVM и омогућила оптимизацију покретања апликација на мобилним уређајима са ограниченом количином RAM-а. Према Google, 2024, Dalvik је обезбеђивао компатибилност апликација кроз JIT-компилацију, претварајући DEX-бајт-код у машинске инструкције непосредно током извршавања.
Главно
Dalvik — виртуелна машина са регистарском архитектуром, направљена посебно за платформу Android. Развој је почео 2005. године у компанији Дена Борнштајна, а 2007. године пројекат је купио Google. Прва комерцијална верзија Dalvik-а појавила се заједно са изласком Android 1.0 2008. године.
За разлику од стандардне Java Virtual Machine (JVM), Dalvik не извршава Java-бајт-код. Java компилатор претвара изворни код у class-датотеке, а затим dx алат преводи исте у формат Dalvik Executable (DEX). Овај формат је компактнији од class-датотека: једна апликација величине 10 MB у class формату заузима око 6–7 MB у DEX-у.
Ден Борнштајн је написао Dalvik као пројекат за оперативне системе са ограниченим ресурсима. Назив је преузет од исландског села Далвик. Google је одабрала Dalvik уместо JVM због лиценцних ограничења и потребе за дубоком оптимизацијом за мобилне процесоре са ARM архитектуром. Систем је брзо стекао популарност: до 2012. године преко 500 милиона Android уређаја је радило на Dalvik-у.
Свака Android апликација покреће се у засебном процесу са сопственом инстанцом Dalvik VM. Ово обезбеђује изолацију података и заштиту од злонамерног кода на нивоу оперативног система. Овакав приступ спаја предности виртуелизације са Linux песчаником — злонамер у једној апликацији не може утицати на суседне процесе.
Регистарска архитектура Dalvik-а се принципијелно разликује од стек архитектуре JVM. Уместо операција са врхом стека, Dalvik оперише регистрима — виртуелним ћелијама унутар VM. Свака инструкција садржи адресе регистара операнда, што смањује број инструкција по једној операцији.
JVM стек машина користи инструкције као што су push, pop и add — за сабирање два броја потребне су три инструкције. Dalvik решава исти задатак једном инструкцијом add-int са три регистра. Према Android Open Source Project, регистарска архитектура DEX-а смањује обим бајт-кода у просеку за 30% у пореџењу са стек class форматом.
DEX-датотека (Dalvik Executable) садржи компримовани приказ свих класа апликације. Заглавље датотеке укључује контролну суму, величине секција и помере. Главне секције су пулови низи, типова, прототипова метода, поља, метода и сам бајт-код. У једној DEX-датотеци може бити похрањено до 65536 метода (ограничење је уклоњено увоџењем multi-dex-а у Android 5.0).
За претварање class-датотека у DEX користи се алат dx, који је део Android SDK Build Tools. Пример наредбе: dx --dex --output=classes.dex myapp.jar. Савремени пројекти користе D8 — наследника dx-а са побољшаном оптимизацијом и подршком за Java 8+ карактеристике.
# Конверзија JAR-а у DEX помоћу dx-а
dx --dex --output=classes.dex myapp.jar
# Савремена верзија кроз D8
d8 --lib android.jar --output dex/ myapp.jar
Процес Zygote — најважнији елемент Dalvik архитектуре. При покретању система, Zygote учитава све класе Android SDK, отвара заједничке библиотеке и ствара пул претходно учитаних ресурса. Кад корисник отвори апликацију, систем копира Zygote процес (fork), стварајући нову инстанцу Dalvik VM са већ готовим оквиром. Ово скраћује време покретања апликације са ~2–3 секунде на 300–500 милисекунди.
JIT (Just-In-Time) — технологија компилације бајт-кода у машинске инструкције непосредно током извршавања апликације. У Dalvik-у, JIT компилатор анализира DEX-код који се извршава, препознаје често коришыене (hot) методе и компилира их у нативни код за CPU.
Избор JIT уместо пуне Ahead-Of-Time (AOT) компилације у ранијим верзијама Android-а био је свесан. Мобилни уређаји су имали ограничену флеш меморију (4–16 GB) — претходна компилација свих апликација би заузела значајан простор. Поред тога, ROM меморија у ранијим уређајима радила је спорије од RAM-а, и читање унапред компилираног кода могло је смањити перформансе.
Кад се апликација покрене, Dalvik почиње да тумачи DEX-бајт-код. Посебан профилер прати које се методе најчешће позивају. Након преласка прага (обично ~200 позива), JIT компилатор претвара методу у машински код и кешира је у RAM-у. Каснији позиви користе већ компилирану верзију без поновне компилације.
// Пример hot методе коју ће JIT компилирати
public class Calculator {
public int sumArray(int[] arr) {
int total = 0;
for (int i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
}
}
Према Google I/O 2013, увоџење JIT-а у Android 2.2 Froyo је убрзало извршавање апликација у просеку 2–5 пута у пореџењу са чистим тумачењем. Међутим, JIT додаје кашњење при првом покретању: апликацији је потребно од 3 до 10 секунди за загревање и компилацију hot метода. Након загревања, перформансе се стабилизује на нивоу блиском нативном коду.
Dalvik се разликује од JVM по неколико фундаменталних параметара. Прво — архитектура: JVM је стек, Dalvik је регистарска. Друго — формат бајт-кода: JVM користи class-датотеке, Dalvik — DEX. Треће — управљање меморијом: Dalvik је оптимизован за ограничену RAM мобилних уређаја.
Оба приступа имају снажне стране. JVM стек захтева мање простора за складиштене инструкција — свака инструкција је краћа јер се операнди имплицитно узимају са стека. Dalvik регистарска извршава мање инструкција по једној операцији, што штеди време процесора и смањује потрошњу енергије. За мобилне уређаје на батерију ово је критично.
| Параметар | Dalvik | JVM |
|---|---|---|
| Архитектура | Регистарска | Стек |
| Бајт-код | DEX | class |
| Компилација | JIT (Android 2.2+) | JIT / AOT |
| Оптимизација | Ниска потрошња енергије | Висока компатибилност |
| Изолација | Кроз Linux процесе | Кроз ClassLoader |
Избор Dalvik-а уместо JVM такође је био условљен лиценцирањем. Oracle поседује права на Java SE и JVM, а Google је желео да избегне лиценцних накнада. Стварање сопствене VM са алтернативним форматом бајт-кода омогућило је Android-у да се развија независно од Oracle-а. Овај спор је прерасао у вишегодишњи судски процес Oracle vs Google (2010–2021), завршен у корист Google-а.
DEX (Dalvik Executable) — бинарни формат који садржи компилирани код Android апликације. Свака DEX-датотека почиње заглављем (header), након којег следе секције: константни низови (string_ids), типови (type_ids), прототипови метода (proto_ids), поља (field_ids), методи (method_ids), дефиниције класа (class_defs) и област података (data).
Алат dx претвара Java class-датотеке у једну или више DEX-датотека. Алгоритам рада укључује дедупликацију константи — исти низови или типови се чувају једном и позивају се преко индекса. Ово значајно смањује коначну величину. У савременим пројектима dx је замијењен са D8 (појавио се у Android Studio 3.1), који је 2–3 пута бржи и подржава Java 8 десахаринг.
// Пример декомпилираног DEX-бајт-кода кроз dexdump
// Изворни код: return a + b;
@Ldalvik/annotation/Code;
registers: 3
add-int v0, v1, v2
return v0
Ограничење DEX формата на 65536 метода (лимит 16-битног индекса) постало је озбиљан проблем за велике апликације. Решење је стигло у Android 5.0: подршка за multi-dex омогућује апликацији да садржи више DEX-датотека. Главни classes.dex садржи улазне тачке, а додатне classes2.dex, classes3.dex и тако даље — остали код. Конфигурација multi-dex-а се укључује у build.gradle линијом multiDexEnabled true.
Сакупљање смећа у Dalvik-у је имплементирано као генерацијски (generational) сакупљач са обележавањем и чишћењем (mark-and-sweep). Меморија је подељена на две главне области: Heap (гомила) за објекте и Stack (стек) за примитиве и референце. Кад се Heap испуни, Dalvik зауставља све нити (STW — Stop-The-World), обележава доступне објекте и ослобађа недоступне.
До Android 2.2, Dalvik је користио једнонитни сакупљач са паузама до 100–200 ms. У Android 2.3 Gingerbread појавио се конкурентни сакупљач, смањујући типичне паузе на 5–10 ms. А у Android 4.0 Ice Cream Sandwich додат је сакупљач са делимичним (incremental) чишћењем — Concurrent Mark and Sweep (CMS).
Типичан проблем Dalvik апликација — цурење меморије кроз статичке референце на Activity. Ако статичко поље чува референцу на Context или View, сакупљач смећа не може да ослободи Activity чак након затварања екрана. Алати попут Eclipse MAT и LeakCanary помажу да се открију такви цурења: анализирају Heap испис и приказују ланце референци које држе објекат.
// Пример цурења меморије кроз статичку референцу
public class Utils {
private static Context context;
public static void init(Context ctx) {
context = ctx; // Држи Activity након finish()
}
}
Упркос успеху, Dalvik је имао низ недостатака. JIT-компилација је захтевала време за загревање — прве секунде рада апликације су биле спорије. Поред тога, JIT је трошио енергију процесора током компилације, што је скраћивало време рада на батерију. Са порастом перформанси мобилних уређаја и повећањем количине уграђене меморије, потреба за JIT-ом је опала.
У Android 4.4 KitKat, Google је представила ART (Android Runtime) као експерименталну замену за Dalvik. Од Android 5.0 Lollipop, ART је постао једино извршно окружење. Главна разлика — AOT компилација: уместо компилације током рада, све апликације се компилирају у машински код при инсталацији. Ово је елиминисало кашњења загревања и побољшало енергетску ефикасност.
Прелазак са Dalvik-а на ART био је транспарентан за програмере: оба окружења извршавају исти DEX-бајт-код. Апликације направљене за Dalvik раде на ART-у без поновне компилације — system_server их компилира у нативни код при инсталацији. Изузетак је код који користи рефлексију за приступ унутрашњим члановима Dalvik VM: такав код би могао да се поквари на ART-у због промене унутрашње архитектуре.
Често постављана питања
Dalvik је програм посредник који покреће Android апликације на телефону. Он узима код апликације и га претвара у наредбе које процесор разуме, радећи то непосредно током рада корисника.
Dalvik користи регистарску архитектуру и DEX формат, док JVM користи стек архитектуру и class формат. Dalvik је оптимизован за мобилне уређаје са ограниченом меморијом и процесором, док је JVM намењена за стационарне рачунаре и сервере.
ART пружа вишу перформансу захваљујући претходној AOT компилацији — апликација се компилира једном при инсталацији, а не сваки пут при покретању. Ово убрзава рад и штеди батерију у пореџењу са JIT приступом Dalvik-а.
Да, ART је потпуно уназад компатибилан са DEX-бајт-кодом Dalvik-а. При инсталацији, ART компилира старе DEX-датотеке у нативни код. Изузетак су апликације које користе рефлексију за приступ унутрашњим механизмима Dalvik-а.
DEX (Dalvik Executable) — формат извршног фајла који садржи компримовани бајт-код Android апликације. У једном APK-у може бити више DEX-датотека (multi-dex), ако апликација садржи више од 65536 метода.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође