Runtime یک لایه نرمافزاری است که اجرای کد اپلیکیشن موبایل را مدیریت میکند: حافظه اختصاص میدهد، استثناها را پردازش میکند، garbage collection را اجرا میکند و فراخوانی متدها را توزیع میکند. بدون runtime هیچ اپلیکیشنی نمیتواند اجرا شود — این لایه میانی بین کد کامپایلشده و سیستم عامل است. طبق Android Developer Documentation, 2025 محیط اجرا عنصر کلیدی پلتفرم است که عملکرد و سازگاری را تعیین میکند.
نکات اصلی
Runtime (محیط اجرا) زیرساختی است که اجرای برنامه را پس از راهاندازی آن فراهم میکند. در زمینه توسعه موبایل runtime شامل بارگذار کلاس، تخصیصدهنده حافظه، garbage collector، توزیعکننده متد و پردازنده استثنا است. بدون این لایه میانی سیستم عامل نمیتواند بایتکد Dalvik یا پیامهای Objective-C را اجرا کند.
پلتفرمهای موبایل از پیادهسازیهای مختلف runtime استفاده میکنند. اندروید از ART (Android Runtime) با کامپایل ترکیبی AOT/JIT استفاده میکند. iOS از Objective-C Runtime استفاده میکند — سیستم پویایی مبتنی بر message passing و شناسههای SEL. هر دو رویکرد یک مسئله را حل میکنند: اجرای کد توسعهدهنده روی دستگاه مشخص با حداکثر کارایی.
طبق Google I/O 2024، Android Runtime روزانه بیش از 10 میلیارد متد را روی دستگاههای سراسر جهان پردازش میکند. عملکرد runtime مستقیماً بر سرعت راهاندازی اپلیکیشن، روانی انیمیشنها و مصرف باتری تأثیر میگذارد. هر فراخوانی متد، هر تخصیص حافظه و هر چرخه garbage collection از لایه runtime عبور میکند.
Runtime system شامل پنج جزء کلیدی است: بارگذار کلاس، مدیریت حافظه، مفسر یا کامپایلر، توزیعکننده متد و سیستم امنیتی. هر جزء عملکرد کاملاً مشخصی در فرآیند اجرای کد انجام میدهد.
وقتی کاربر اپلیکیشن را راهاندازی میکند، ClassLoader فایلهای DEX (اندروید) یا باینریهای Mach-O (iOS) را در حافظه رم بارگذاری میکند. در اندروید این مرحله شامل تأیید صحت بایتکد است: runtime بررسی میکند که کد حاوی دستورالعملهای ناامن نباشد، از مرز آرایهها خارج نشود و انواع را رعایت کند. تأیید صحت یک گام امنیتی حیاتی است که از اجرای کد مخرب جلوگیری میکند.
Memory Manager حافظه را برای اشیاء تخصیص و آزاد میکند. در اندروید ART از garbage collector همزمان با جمعآوری نسلی استفاده میشود: اشیاء جوان بیشتر و اشیاء قدیمی کمتر بررسی میشوند. Objective-C Runtime از Automatic Reference Counting (ARC) استفاده میکند که در آن کامپایلر فراخوانیهای retain/release را بهطور خودکار وارد میکند.
Method dispatcher تعیین میکند کدام پیادهسازی متد فراخوانی شود. در زبانهای ایستا (Kotlin, Swift) توزیع از طریق vtable — جدول متدهای مجازی انجام میشود. در زبانهای پویا (Objective-C) پیام از objc_msgSend عبور میکند که پیادهسازی را در کلاس و سوپرکلاسهای آن جستجو میکند. نتیجه برای سرعت بخشیدن به فراخوانیهای مکرر در method cache ذخیره میشود.
Android Runtime (ART) ماشین مجازی است که بایتکد DEX اپلیکیشنهای اندروید را اجرا میکند. ART در اندروید 5.0 Lollipop جایگزین Dalvik شد و کامپایل AOT را ارائه داد: اپلیکیشن یک بار در هنگام نصب به کد ماشینی کامپایل میشود. این کار هزینه اضافی کامپایل JIT در هر راهاندازی را حذف کرد.
از اندروید 7.0 Nougat، ART از رویکرد ترکیبی استفاده میکند. در هنگام نصب کامپایل JIT فقط برای متدهای پرکاربرد (hot methods) انجام میشود و بقیه کد تفسیر میشود. فرآیند پسزمینه (profile-guided optimization) تحلیل میکند کدام متدها بیشتر فراخوانی میشوند و آنها را در زمان بیکاری دستگاه AOT کامپایل میکند. این کار زمان نصب را کاهش میدهد و همزمان عملکرد بالایی را فراهم میکند.
ART همچنین شامل AOT compiler (dex2oat) است که فایلهای DEX را به باینریهای ELF با کد ماشینی ARM64 تبدیل میکند. کامپایل با سه سطح بهینهسازی انجام میشود: quicken (سریع)، optimize (متوسط) و everything (کامل). اندروید بهطور پیشفرض optimize را اعمال میکند که بین سرعت کامپایل و عملکرد کد تعادل ایجاد میکند.
class RuntimeExample {
fun measureExecutionTime() {
val start = System.nanoTime()
// فراخوانی متدی که توسط ART کامپایل میشود
processData()
val end = System.nanoTime()
println("زمان اجرا: ${end - start} نانوثانیه")
}
}در مثال بالا System.nanoTime() یک متد بومی است که فراخوانی آن از طریق runtime ART به هسته لینوکس توزیع میشود. ART بایتکد کاتلین را به دستورالعملهای ARM64 تبدیل میکند که توسط پردازنده دستگاه اجرا میشوند. این فرآیند بهطور نامحسوس برای توسعهدهنده اتفاق میافتد، اما بهینهسازی آن وظیفه کلیدی تیم Android Platform است.
بهینهسازی مبتنی بر پروفایل مکانیزم ART است که پروفایلهای استفاده از متدها را جمعآوری میکند. فایل profiles/
توسعهدهنده میتواند در پروژه Gradle خود baseline profiles را فعال کند. اینها توضیحنویسیهای دستی هستند که به ART نشان میدهند کدام متدها بلافاصله پس از نصب AOT کامپایل شوند. Baseline profiles اولین راهاندازی را بدون انتظار برای پروفایلگیری پسزمینه 40 درصد کوتاه میکنند.
Objective-C Runtime کتابخانه پویایی است که اجرای کد Objective-C را در iOS و macOS فراهم میکند. هسته آن تابع objc_msgSend است که message passing را پیادهسازی میکند: به جای فراخوانی مستقیم متد، شیء پیامی با selector میفرستد و runtime تعیین میکند کدام پیادهسازی باید اجرا شود.
هر شیء Objective-C حاوی اشارهگر isa به کلاس است و کلاس دارای dispatch table (جدول توزیع) است که selectorها (SEL) را به پیادهسازیها (IMP) نگاشت میکند. وقتی متدی فراخوانی میشود، objc_msgSend در طول زنجیره حرکت میکند: کلاس ← سوپرکلاس ← NSObject تا IMP پیدا شود. اگر پیادهسازی پیدا نشود، runtime مکانیزم forwarding را فعال میکند که میتواند پیام را رهگیری یا استثنا ایجاد کند.
Objective-C Runtime همچنین از method swizzling پشتیبانی میکند — جایگزینی IMP برای selector موجود در حین اجرا. این مکانیزم قدرتمندی است که در کتابخانههای AOP و ابزارهای مانیتورینگ استفاده میشود، اما به دلیل تأثیر بر کل اپلیکیشن نیازمند احتیاط است.
@interface RuntimeDemo : NSObject
- (void)printClassInfo;
@end
@implementation RuntimeDemo
- (void)printClassInfo {
// objc_getClass — تابع runtime
Class cls = objc_getClass("RuntimeDemo");
unsigned int count;
Method *methods = class_copyMethodList(cls, &count);
NSLog("تعداد متدها: %d", count);
}
@endکد دسترسی مستقیم به Objective-C Runtime API را نشان میدهد: objc_getClass شیء کلاس را با نام به دست میآورد، class_copyMethodList فهرست همه متدها را استخراج میکند. این reflection در عمل است — دسترسی به متادیتای کلاس در حین اجرا. چنین رویکردی در XCTest برای ثبت پویای تستها استفاده میشود.
isa pointer اشارهگری به کلاس شیء است که در 8 بایت اول هر شیء ذخیره میشود. از iOS 12، اپل isa-swizzling را برای بهینهسازی معرفی کرد: بیتهای پایین isa اطلاعات اضافی درباره وضعیت شیء را کدگذاری میکنند. Tagged pointers بهینهسازی دیگری است که در آن مقادیر تا 60 بیت (NSNumber, NSDate) مستقیماً در اشارهگر ذخیره میشوند، بدون تخصیص شیء در heap. این بار مدیریت حافظه را 30 درصد کاهش میدهد.
JIT (Just-In-Time) و AOT (Ahead-Of-Time) دو رویکرد برای کامپایل بایتکد به کد ماشینی هستند. JIT کد را در حین اجرای اپلیکیشن کامپایل میکند، بخشهای داغ را تحلیل و آنها را در لحظه بهینه میکند. AOT کل کد را از قبل — هنگام نصب اپلیکیشن یا در سمت توسعهدهنده — کامپایل میکند.
| مشخصه | JIT | AOT |
|---|---|---|
| زمان کامپایل | در حین اجرا | در هنگام نصب / بیلد |
| اندازه APK/IPA | کوچکتر (فقط بایتکد) | بزرگتر (کد ماشینی) |
| سرعت راهاندازی | کمتر (کامپایل لازم است) | بیشتر (کد آماده اجراست) |
| بهینهسازی برای دستگاه | بله (تطبیقی) | محدود (generic) |
| مصرف RAM | بیشتر (کامپایلر در حافظه) | کمتر |
رویکرد ترکیبی ART (اندروید 7+) بهینه در نظر گرفته میشود: اپلیکیشن برای متدهای کمفراخوانی از مفسر، برای متدهای hot از JIT و برای متدهای حاصل از profile-guided optimization از AOT استفاده میکند. iOS در مقابل از AOT سختگیرانه از طریق LLVM استفاده میکند: Swift و Objective-C در مرحله بیلد در Xcode به کد ماشینی کامپایل میشوند.
طبق Apple Developer Documentation, 2024، Swift runtime حدود 15 مگابایت به اندازه اپلیکیشن اضافه میکند. Flutter از Dart VM خود استفاده میکند که در آن کامپایل JIT برای hot reload در حالت debug و AOT برای حداکثر کارایی در حالت release کار میکند. React Native از Hermes — موتور جاوااسکریپت با کامپایل AOT که زمان راهاندازی را 50 درصد کوتاه میکند — استفاده میکند.
ARM64 Runtime سطحی است که کد ماشینی با پردازنده دستگاه تعامل دارد. اکثر دستگاههای موبایل مدرن روی پردازندههای ARM64 (aarch64) کار میکنند. Runtime بایتکد یا فراخوانیهای بومی را به دستورالعملهای ARM64 ترجمه میکند که CPU آنها را اجرا میکند.
رجیسترهای کلیدی ARM64 که runtime استفاده میکند: x0–x7 (پارامترهای توابع)، x8 (نتیجه غیرمستقیم)، x30 (آدرس بازگشت)، sp (stack pointer)، fp (frame pointer). ART کدی تولید میکند که از ARM64 Procedure Call Standard پیروی میکند: همه فراخوانیهای متد از پروتکلی که توسط معماری پردازنده تعریف شده عبور میکنند.
درک ARM64 ABI در بهینهسازی عملکرد مهم است: inline-caching، پیشبینی انشعاب و همترازی کد در حافظه مستقیماً بر سرعت کار runtime تأثیر میگذارد. ابزارهای پروفایلگیری (Android Studio Profiler, Instruments) نشان میدهند کدام بخشهای کد بیشترین زمان را در runtime میگذرانند — بهینهسازی همین بخشها بیشترین افزایش را میدهد.
// نمونه ARM64 assembly تولیدشده توسط ART
// فراخوانی متد با دو پارامتر
mov x0, x23 // self (this)
mov x1, x24 // param1
mov x2, x25 // param2
bl methodEntryPoint // فراخوانی از طریق runtime
str x0, [sp, #8] // ذخیره نتیجهدر این مثال دستورالعملهای ARM64 mov آرگومانها را به رجیسترهای x0–x2 منتقل میکنند، bl نقطه ورود متد را فراخوانی میکند و str مقدار بازگشتی را ذخیره میکند. Runtime چنین دستورالعملهایی را برای هر فراخوانی متد تولید میکند و دنباله را از طریق devirtualization و inlining بهینه میکند.
Runtime overhead هزینه اجتنابناپذیر توزیع پویا است. هر فراخوانی متد از طریق runtime نیاز دارد: جستجوی پیادهسازی در dispatch table، بررسی انواع، فراخوانی IMP و بازگرداندن نتیجه. اندازهگیریها نشان میدهد که runtime در Objective-C 10 تا 50 نانوثانیه و در ART 5 تا 20 نانوثانیه به هر فراخوانی اضافه میکند.
برای کاهش هزینه، توسعهدهندگان از monomorphic inlining (ART) و method caching (Objective-C) استفاده میکنند. Kotlin/Native و Swift مستقیماً به ARM64 کامپایل میشوند و لایه runtime را کاملاً حذف میکنند، اما قابلیتهای پویا — reflection، swizzling، بارگذاری پویای کلاس — را از دست میدهند.
سؤالات متداول
SDK (Software Development Kit) مجموعه ابزارهای توسعه اپلیکیشن است (کامپایلر، کتابخانهها، ابزارها). Runtime محیطی است که اپلیکیشن از پیش توسعهیافته در آن روی دستگاه اجرا میشود. SDK برای توسعهدهنده لازم است، runtime برای کاربر.
خیر — runtime بخشی از سیستم عامل است و نمیتواند توسط کاربر جایگزین شود. ART در Android Framework و Objective-C Runtime در iOS تعبیه شده است. توسعهدهنده میتواند زبان را انتخاب کند (Kotlin/Native بدون runtime) یا از ماشینهای مجازی مانند Dart VM در Flutter استفاده کند.
بله، runtime بر مصرف انرژی تأثیر میگذارد. Garbage collection در ART و Swift runtime از CPU استفاده میکنند که مصرف باتری را افزایش میدهد. بهینهسازیهایی مانند concurrent GC و tagged pointers در iOS تأثیر runtime بر باتری را 20 تا 30 درصد کاهش میدهند.
Runtime error خطایی است که در حین اجرا رخ میدهد: null pointer exception، index out of bounds، تقسیم بر صفر. برخلاف خطاهای compile-time، این خطاها در هنگام بیلد شناسایی نمیشوند. از طریق بلوکهای try-catch یا crash reporting (Firebase Crashlytics, Sentry) گرفته میشوند.
Swift runtime سبکتر از Objective-C است: بهطور پیشفرض از dynamic dispatch پشتیبانی نمیکند، از value types (struct) بدون تخصیص در heap استفاده میکند و message forwarding ندارد. متدهای Swift اگر با @objc dynamic علامتگذاری نشده باشند مستقیماً از طریق vtable فراخوانی میشوند. این در benchmarkها تا 5 برابر افزایش سرعت میدهد.
نتایج
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید