Android Runtime (ART) — az Android-alkalmazások futási környezete, amely az Android 5.0 Lollipopban került bevezetésre a Dalvik helyettesítésére. A fő újítás — a DEX bájtkód előzetes AOT fordítása natív gépi kódra közvetlenül az alkalmazás telepítésekor, ami megszüntette a JIT fordító felmelegedésének évek óta fennálló problémáját. A Google, 2024 szerint az ART 20–30%-os teljesítménynövekedést biztosít a Dalvikhoz képest, miközben megtartja a teljes visszamenőleges kompatibilitást a DEX formátummal.
Főbb pontok
Android Runtime (ART) — az alkalmazások futási környezete, amely a DEX bájtkódot natív gépi kódra fordítja a futtatás előtt. Ellentétben a Dalvikkal, amely Just-In-Time fordítást használt futás közben, az ART Ahead-Of-Time (AOT) fordítást végez az APK telepítésekor. Ez az alapvető architektúra-változás az alkalmazások jelentős gyorsulásához és az energiafogyasztás csökkenéséhez vezetett.
Az ART először kísérleti opcióként jelent meg az Android 4.4 KitKatban. A fejlesztők bekapcsolhatták a fejlesztői beállításokban és tesztelhették az alkalmazásaikat. Az Android 5.0 Lollipopban az ART lett az alapértelmezett futási környezet, és a Dalvikot teljesen eltávolították a platformból. Az Android 7.0 Nougat megjelenésére az ART hibrid fordítási módot kapott.
A Dalvik ART-ra cserélésének döntése nem volt hirtelen. Az új környezeten végzett munka 2012-ben kezdődött, amikor a Google felismerte a JIT megközelítés korlátait. Fő célok: az alkalmazások indításának gyorsítása, a processzor terhelésének csökkentése és az energiafogyasztás mérséklése. A fejlesztést a Android Runtime Group csapat vezette, amely korábban a Dalvik optimalizálásán dolgozott.
Az ART ugyanazt a regiszterarchitektúrát használja, mint a Dalvik, de teljesen újratervezett fordítóval. Interpretáló és JIT fordító helyett az ART az AOT fordítót, a dex2oat-ot tartalmazza, amely a DEX fájlokat ELF binárisokká alakítja telepítéskor. Ennek eredményeként az ART-n futó alkalmazás azonnal natív teljesítménnyel indul, felmelegedési fázis nélkül.
ART megtartotta a Dalvik kulcsfontosságú elveit: az alkalmazások elkülönítését külön folyamatokon keresztül, a regiszterarchitektúrát és a DEX formátum támogatását. A belső implementációt azonban teljesen újraírták. A Dalvik interpretáló helyett az ART három végrehajtási módot tartalmaz: interpretáló, JIT fordító és AOT fordító dex2oat. A mód kiválasztása az alkalmazás életciklusának szakaszától függ.
Az ART kulcsfontosságú összetevője — a dex2oat (dalvik executable to optimized android translator). Ez az eszköz az alkalmazás telepítésekor indul el (Android 7.0-tól — háttéroptimalizáláskor is). A dex2oat kiolvassa a DEX fájlokat az APK-ból, optimalizálja a bájtkódot, és generál egy OAT fájlt — egy ELF binárist natív kóddal. Az OAT fájlok a /data/dalvik-cache/ könyvtárban tárolódnak.
# OAT fájlok ellenőrzése az eszközön
adb shell ls -la /data/dalvik-cache/arm64/
# Az alkalmazás kényszerített újrafordítása
adb shell cmd package compile -m speed com.example.app
Az ART rendszer több összekapcsolt modulból áll. A dex2oat fordító felelős a natív kód generálásáért. A szemétgyűjtő (GC) kezeli a memória felszabadítását. Az interpretáló a ritkán hívott kódot fordítja le. A profilozó a hot metódusokat követi nyomon a hibrid fordításhoz. Minden modul függetlenül működhet, ami az ART-ot rugalmassá és skálázhatóvá teszi.
Az Android 7.0 Nougat-tól kezdve az ART hibrid megközelítést használ a fordításhoz, ötvözve a JIT és AOT előnyeit. Az alkalmazás telepítésekor az ART már nem végez teljes AOT fordítást — ehelyett az alkalmazás interpretált módban indul a hot metódusok JIT fordításával. Ez csökkenti a telepítési időt és a foglalt helyet.
Párhuzamosan működik a háttérprofilozó (background profiler). Végrehajtási statisztikákat gyűjt: mely metódusokat hívják a leggyakrabban, mely kódágak hajtódnak végre, mely osztályok töltődnek be. Elegendő adat összegyűjtése után (általában 2–3 alkalmazásindítás után) az ART elindítja a dex2oat-ot a háttérben, és csak a profilozott hot metódusokat fordítja le natív kódra.
ART több, a system_server-en keresztül kezelt fordítási módot támogat. A "speed" mód az összes metódust AOT-ra fordítja (maximális teljesítmény, hosszú telepítés). A "speed-profile" mód csak a profilozott hot metódusokat fordítja (egyensúly a sebesség és méret között). A "verify" mód csak ellenőrzi a bájtkódot fordítás nélkül (minimális hely, interpretálás). Alapértelmezetten a speed-profile használatos — optimális a legtöbb alkalmazáshoz.
| Mód | Fordítás | Telepítési idő | Teljesítmény |
|---|---|---|---|
| speed | Teljes AOT | Hosszú | Maximális |
| speed-profile | Profilozott AOT | Gyors | Magas |
| verify | Fordítás nélkül | Azonnali | Interpretálás |
| space | Minimális AOT | Közepes | Közepes |
A profilozó végrehajtási adatokat gyűjt speciális .prof fájlokba. Minden alkalmazás a saját profilját a /data/misc/profiles/ mappában tárolja. A küszöb elérésekor (általában 1000 minta) a profilozó elindítja a dex2oat-ot az azonosított hot metódusok lefordításához. A profilok megmaradnak az alkalmazásfrissítések között, ami felgyorsítja az újraoptimalizálást a rendszer OTA frissítései után.
Szemetgyűjtés az ART-ban gyökeresen javult a Dalvikhoz képest. Az egyszálú Concurrent Mark and Sweep (CMS) helyett az ART generációs gyűjtőt használ több optimalizálással: moving collector (heap tömörítés), large object space (nagy objektumok külön tárolása) és concurrent compaction (párhuzamos tömörítés).
Egy tipikus GC szünet az ART-ban 2–3 ms szemben a Dalvik 5–10 ms-ával. Ez több mechanizmusnak köszönhetően vált lehetővé. Először is, az ART read-barrier-t használ stop-the-world helyett a konkurens fázisokhoz. Másodszor, a generációs gyűjtő a legtöbb ciklusban csak a fiatal generációs objektumokat dolgozza fel, nem érintve a teljes heap-et. Harmadszor, a large object space (LOS) külön van allokálva, és nem vesz részt a szokásos GC ciklusokban.
// GC naplók engedélyezése hibakereséshez
System.logV("ART", "GC trigger: allocation failed");
// Kényszerített GC hívás (nem ajánlott élesben)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Debug.getRuntimeIStats();
}
A javított GC ellenére a memóriaszivárgás továbbra is aktuális probléma marad. Az ART-specifikus ok — natív könyvtárak betöltése JNI-n keresztül megfelelő felszabadítás nélkül. Ha a natív kód malloc-on keresztül allokál memóriát, de nem hívja meg a free-t, az ART nem tudja felszabadítani ezt a memóriát — az a kezelt heapen kívül helyezkedik el. Az Android NDK-beli AddressSanitizer eszköz segít az ilyen szivárgások felderítésében.
ART és Dalvik — ugyanazon feladat két alapvetően eltérő megvalósítása: Android-alkalmazások futtatása. A különbségek minden szintet érintenek: a fordítástól a memóriakezelésig. Az alábbiakban a fő teljesítmény- és kompatibilitási paraméterek összehasonlítása látható.
Az ART fő előnye — a JIT felmelegedés megszüntetése. Dalvikon az alkalmazás az első 3–10 másodpercben lassulhatott, amíg a JIT fordította a hot metódusokat. ART-on az összes metódus már natív kódra van fordítva (vagy a háttérben lesz lefordítva). Ez különösen észrevehető játékokban és nehéz UI-val rendelkező alkalmazásokban: az fps különbség elérheti a 15–20%-ot az ART javára.
| Paraméter | Dalvik | ART |
|---|---|---|
| Fordítás | JIT (futás közben) | AOT + hibrid (telepítéskor) |
| Indítási idő | 3–10 mp (felmelegedés) | Azonnali |
| APK méret | ~6–7 MB (DEX) | +20% (OAT) |
| GC szünetek | 5–10 ms | 2–3 ms |
| Energiafogyasztás | Magasabb (JIT melegíti a CPU-t) | Alacsonyabb (natív kód) |
Minden Dalvikra írt alkalmazás ART-on változtatás nélkül működik. A Google teljes visszamenőleges kompatibilitást garantál a DEX bájtkód szintjén. Kivétel — a Dalvik-specifikus belső API-t reflexióval használó kód: a dalvik.system.DexFile osztály @hide-dal jelölt tagjai az Android SDK-ban. Az ilyen kódot frissíteni kell a nyilvános API-k használatára.
ART lett az első Android futási környezet natív Java 8 funkciótámogatással. Az Android 7.0-tól kezdve az ART tartalmazza a desugaring-ot — a Java 8 konstrukciók (lambdák, method references, Stream API) ekvivalens Java 7 kódra alakításának folyamatát. Ez lehetővé teszi a modern szintaxis használatát anélkül, hogy elveszítené a kompatibilitást a régebbi eszközökkel.
A desugaring-ot a D8 fordító végzi, és a következőképpen működik. A lambdát tartalmazó forráskód egy szintetikus metódussá alakul ugyanabban az osztályban, a lambda pedig egy invoke-custom hívásra cserélődik. Az ART futási környezete támogatja az invoke-custom utasítást, amelyet kifejezetten a Java 8-hoz adtak hozzá. Az Android 6.0-s és alacsonyabb verziójú eszközökön a lambdák anonim osztályokká desugargálódnak.
// Java 8 lambda — desugaring ART-ban
button.setOnClickListener(v -> handleClick(v));
// Desugaring után (egyenérték Java 7-ben)
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleClick(v);
}
});
Nem minden Java 8 funkciót támogat a desugaring. A java.time API (dátum és idő) csak a desugar_jdk_libs-en keresztül érhető el — egy kiegészítő könyvtáron keresztül, amelyet a build.gradle-ben kell hozzáadni. A Stream API szintén desugar_jdk_libs-t igényel. A java.util.function és Optional további függőségek nélkül működik. A teljes Java 8 támogatás Android 8.0-s és újabb eszközökön desugaring nélkül érhető el.
Bár az ART visszamenőlegesen kompatibilis, néhány optimalizálási gyakorlat éppen ezen a környezeten javítja a teljesítményt. A fő ajánlás — minimalizáljuk a reflexiót. Az ART a fordítási fázisban látható metódusokat közvetlen gépi kódhívásra fordítja. A Reflexió arra kényszeríti az ART-ot, hogy további stub-okat generáljon, ami 10–15%-kal lassítja a végrehajtást.
Az Android 9.0-tól kezdve az ART támogatja az App Startup Optimization-t. A fejlesztő megjelölheti az inicializáló osztályokat a manifestben a <initialization> segítségével, és az ART előre betölti őket az alkalmazás indításakor. Ez 5–15%-kal csökkenti az indítási időt a sok beépülő modullal vagy könyvtárral rendelkező alkalmazásoknál.
<!-- App Startup Optimization az AndroidManifest.xml-ben -->
<application>
<profileable
android:shell="true"
android:enable="true" />
</application>
A teljesítmény méréséhez ART-on használja a systrace és perfetto eszközöket. A Systrace mutatja a dex2oat fordítási idejét, a GC gyakoriságát és a képkockasebességet. A Perfetto részletesebb információkat nyújt: szálak eloszlása, JNI átmenetek ideje, natív könyvtárak betöltése. Indítás: adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto -t 10s sched freq idle am wm.
Gyakran ismételt kérdések
ART (Android Runtime) — az Android-alkalmazások futási környezete, amely az alkalmazás kódját telepítéskor gépi kódra fordítja. Ez gyorsabbá teszi az alkalmazások indítását és működését a régi Dalvik környezethez képest.
ART előre (AOT) fordítja a kódot az alkalmazás telepítésekor, míg a Dalvik futás közben darabonként (JIT) fordította. Ezért ART-on az alkalmazások gyorsabban indulnak és kevesebb energiát fogyasztanak.
Futtassa a adb shell getprop parancsot, és keresse meg a persist.sys.dalvik.vm.lib.2 tulajdonságot. A "libart.so" érték ART-ot, a "libdvm.so" — Dalvikot jelent. Minden Android 5.0+ rendszerű eszközön a futási környezet ART.
Kismértékben. Maga az alkalmazás APK formátumban marad DEX fájlokkal. Az ART létrehoz egy további OAT fájlt a /data/dalvik-cache/ mappában, amely 10–20%-kal több helyet foglal, mint az eredeti DEX, de ez a tárhely nem számít bele az APK méretébe.
Igen, ART a desugaring mechanizmuson keresztül támogatja a Java 8 funkciók többségét. A lambdák, method references és funkcionális interfészek minden Android 5.0+ rendszerű eszközön működnek. A Stream API-hoz és java.time-hoz a desugar_jdk_libs könyvtár szükséges.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is