ماشین مجازی Dalvik — جزء کلیدی سیستمعامل Android، که مسئول اجرای برنامهها تا نسخه 4.4 KitKat بود. این ماشین مجازی ثباتی که توسط دن بورنشتاین طراحی شد، جایگزین مفهوم JVM استاندارد شد و امکان بهینهسازی راهاندازی برنامهها را در دستگاههای موبایل با حافظه RAM محدود فراهم کرد. به گزارش Google, 2024، Dalvik از طریق JIT-کامپایل اتحاد و تبدیل DEX-بایت-کد به دستورات ماشین بهطور مستقیم در زمان اجرا ایجاد میکرد.
نکات کلیدی
Dalvik — ماشین مجازی با معماری ثباتی، که بهطور ویژه برای پلتفرم Android ساخته شد. توسعه در سال 2005 توسط شرکت دن بورنشتاین آغاز شد و در سال 2007، پروDAژه توسط Google خریداری شد. نخستین نسخه تجاری Dalvik همراه با انتشار Android 1.0 در سال 2008 منتشر شد.
به علاوه بر ماشین مجازی استاندارد Java (JVM)، Dalvik کد بایت Java را اجرا نمیکند. کامپایلر Java کد مبنا را به فایلهای class تبدیل میکند، سپس ابزار dx آنها را به فرمت Dalvik Executable (DEX) ترجمه میکند. این فرمت از فایلهای class مرتکبتر است: یک برنامه 10 مگابایتی در فرمت class در DEX تقریباً 6–7 مگابایت اشغال میدهد.
دن بورنشتاین Dalvik را به عنوان پروDAژهای برای سیستمهای عامل با منابع محدود نوشت. نام آن از روستای دالویک در ایسلند گرفته شده است. Google به دلیل محدودیتهای مجوز و نیاز به بهینهسازی عمیق برای پردازندههای موبایل با معماری ARM، Dalvik را به جای JVM انتخاب کرد. سیستم سریعاً محبوب شد: تا سال 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. پروDAژههای مدرن از 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 را کپی میکند (فورک) و یک نسخه جدید Dalvik VM با فریمورک آماده ایجاد میکند. این زمان راهاندازی برنامه را از ~2–3 ثانیه به 300–500 میلیثانیه کاهش میدهد.
JIT (Just-In-Time) — فناوری کامپایل بایت-کد به دستورات ماشین مستقیماً در زمان اجرای برنامه. در Dalvik، کامپایلر JIT کد DEX در حال اجرا را تجزیه و تحلیل میکند، روشهای مکرر (hot) را شناسایی میکند و آنها را به کد مادری برای CPU کامپایل میکند.
انتخاب JIT به جای کامپایل کامل Ahead-Of-Time (AOT) در نسخههای اولیه Android آگاهانه بود. دستگاههای موبایل حافظه فلش محدودی (4–16 گیگابایت) داشتند — کامپایل پیشاز موقع تمام برنامهها حجم قابل توجهی اشغال میکرد. علاوه بر این، حافظه 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 در مقابل 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 تبدیل میکند. الگوریتم کار شامل حذف تکرار ثابتها است — رشتهها یا انواع یکسان یک بار ذخیره شده و با اندیس ارجاع داده میشوند. این حجم نهایی را به طور قابل توجهی کاهش میدهد. در پروDAژههای مدرن، 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 میلیثانیه استفاده میکرد. در Android 2.3 Gingerbread، یک خردودهگیر همزمان وارد شد که مدت وقفه را به 5–10 میلیثانیه کاهش داد. و در 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 از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید