DEX Nedir?
Android'in Kendi Dili
Her platformun uygulamaları çalıştırmak için kullandığı bir format vardır. Windows'ta PE, macOS'ta Mach-O, Linux'ta ELF. Android'in bu formata karşılık gelen çözümü DEX'tir — Dalvik Executable.
DEX, Android Runtime'ın anlayıp çalıştırabileceği bytecode formatıdır. Yazdığınız Kotlin ya da Java kodu derleme sürecinde nihayetinde bu formata dönüşür ve cihazda bu haliyle işlenir.
Neden Standart Java Bytecode Değil?
Bu sorunun cevabı 2003'e, Android'in tasarlandığı döneme gidiyor.
O dönemde standart Java bytecode'u masaüstü ve sunucu sistemleri için optimize edilmişti. Yığın tabanlı (stack-based) bir mimariye sahipti ve bu mimari masaüstü işlemcilerle iyi çalışıyordu. Ama mobil cihazlar için bu yaklaşım ciddi sorunlar yaratıyordu.
Mobil işlemciler 2003'te son derece kısıtlıydı. Bellek son derece değerliydi. Pil ömrü kritikti. Standart JVM, bu kısıtlar altında verimli çalışmak için tasarlanmamıştı.
DEX, bu gerçekliği göz önünde bulundurarak sıfırdan tasarlandı. Register tabanlı (register-based) bir mimari benimsedi. Bu yaklaşım stack tabanlı mimariye kıyasla daha az talimat gerektiriyordu ve daha az talimat daha az işlemci döngüsü, daha az işlemci döngüsü ise daha az pil tüketimi anlamına geliyordu.
DEX Formatının İçi
Bir DEX dosyasının içinde çok sayıda farklı veri havuzu organize bir şekilde tutulur.
String havuzu, uygulama kodundaki tüm sabit string değerlerini tek bir yerde toplar. Aynı string birden fazla yerde kullanılıyorsa DEX bunu tekrar tekrar saklamak yerine tek bir kez depolar ve her kullanım noktası bu ortak kaynağa referans verir.
Tip tanımları, uygulama içindeki tüm sınıf isimlerini ve tip bilgilerini saklar. Metot tanımları ise her metodun adını, parametre tiplerini ve dönüş tipini barındırır.
Bu havuz yapısı DEX'in neden standart .class dosyalarından daha kompakt olduğunu açıklar. Her sınıf için ayrı ayrı saklanan bilgiler DEX'te tek bir ortak havuzda toplanır ve referanslarla paylaşılır.
65.536 Limiti: Meşhur MultiDex Sorunu
DEX formatının en çok konuşulan kısıtlaması metot referans limitidir.
Bir DEX dosyası içinde en fazla 65.536 metot referansı bulunabilir. Bu sayı 2'nin 16. kuvvetidir ve DEX'in metot referanslarını 16 bitlik bir tamsayıyla indekslediğini gösterir.
65.536 çok büyük bir sayı gibi görünebilir. Ama projeniz büyüdükçe ve bağımlılıklarınız arttıkça bu limite beklenmedik bir hızla yaklaşılır. Android Support Library, Jetpack bileşenleri, üçüncü parti kütüphaneler — her biri bu havuza katkıda bulunur.
Bu limiti aşmanın çözümü MultiDex'tir. Uygulama classes.dex, classes2.dex, classes3.dex gibi birden fazla DEX dosyasına bölünür. Android 5.0 ve sonrasında bu destek sistem tarafından sağlanır. Ancak eski cihazlarda MultiDex kütüphanesini ayrıca entegre etmek ve Application sınıfınızı buna göre yapılandırmak gerekir.
ART ve DEX: Çalışma Zamanında Ne Olur?
DEX bytecode cihaza ulaştığında ART bu kodu çeşitli stratejilerle native makine talimatlarına dönüştürür. Bu dönüşümün detaylarını ART yazısında ele almıştık.
Ama burada vurgulanması gereken bir nokta var: DEX bytecode'u cihazda çalışmaz. ART, DEX'i okur ve işlemcinin anlayabileceği native koda çevirir. DEX yalnızca taşıma formatıdır — çalışma formatı değil.
ODEX ve VDEX: Optimize Edilmiş Formlar
Cihaza yükleme sonrasında ART, DEX'ten türetilmiş optimize dosyalar oluşturur.
ODEX (Optimized DEX), ART'ın önceden derlediği ve cihaza özgü hale getirdiği bytecode'u barındırır. VDEX (Verified DEX) ise doğrulama adımını atlayarak sonraki başlatmaları hızlandırmak için kullanılır.
Bu dosyaları doğrudan göremez ve değiştiremezsiniz — bunlar sistem tarafından otomatik olarak yönetilen dahili optimizasyon dosyalarıdır. Ama bir uygulamanın yükleme sonrası ilk çalıştırmasının neden biraz daha yavaş olduğunu anlamak istiyorsanız cevap burada yatar: Bu dosyalar henüz oluşturulmamıştır.
Geliştirici Perspektifinden Bakış
DEX'i anlamak özellikle büyük projelerde ve derleme sürecini optimize etmek istediğinizde kritik hale gelir.
MultiDex sorunlarıyla boğuşurken neyle karşı karşıya olduğunuzu bilmek hem doğru konfigürasyonu yapmanızı hem de bağımlılık sayısını bilinçli yönetmenizi sağlar. R8 ve ProGuard kurallarını yazarken DEX'e nelerin girdiğini anlamak gereksiz kodu eleyip eleyemeyeceğinizi kavramanıza yardımcı olur. Ve cihaz uyumluluk sorunlarıyla karşılaştığınızda sorunun DEX katmanında mı yoksa ART katmanında mı olduğunu ayırt edebilirsiniz.