Runtime في التطوير المحمول: ما هو، نظام runtime وكيف يعمل

المؤلف: IT Sectr نُشر: 2026-05-17 وقت القراءة: 9 دق

Runtime هو طبقة برمجية تدير تنفيذ كود التطبيق المحمول: تخصص الذاكرة، تعالج الاستثناءات، تشغل جمع القمامة وتوزع استدعاءات الدوال. بدون runtime، لا يمكن لأي تطبيق أن يعمل — هو الطبقة الوسيطة بين الكود المترجم ونظام التشغيل. وفقاً لـ Android Developer Documentation, 2025، بيئة التشغيل هي عنصر أساسي في المنصة يحدد الأداء والتوافق.

النقاط الرئيسية

  • Runtime هو البيئة البرمجية التي تنفذ البايت كود أو كود الآلة للتطبيق المحمول.
  • ART (Android Runtime) يستخدم ترجمة AOT وحل محل Dalvik بدءاً من Android 5.0.
  • Objective-C Runtime يوفر التوزيع الديناميكي للدوال وتمرير الرسائل في iOS.
  • ترجمة JIT تترجم البايت كود إلى كود آلة مباشرة أثناء تنفيذ التطبيق.
  • ARM64 Runtime هو المستوى العتادي الذي يُنفذ عليه الكود المحسن لمعالجات ARM ذات 64 بت.

ما هو Runtime في التطوير المحمول؟

Runtime هو البنية التحتية التي تضمن تنفيذ البرنامج بعد تشغيله. في سياق التطوير المحمول، يشمل runtime محمل الفئات، موزع الذاكرة، جامع القمامة، موزع الدوال ومعالج الاستثناءات. بدون هذه الطبقة الوسيطة، لا يمكن لنظام التشغيل تنفيذ بايت كود Dalvik أو رسائل Objective-C.

تستخدم المنصات المحمولة تطبيقات مختلفة لل runtime. Android يستخدم ART (Android Runtime) مع ترجمة هجينة AOT/JIT. iOS يستخدم Objective-C Runtime — نظام ديناميكي يعتمد على تمرير الرسائل ومعرفات SEL. كلا المنهجين يحلان نفس المشكلة: تنفيذ كود المطور على جهاز معين بأقصى أداء.

وفقاً لـ Google I/O 2024، يعالج Android Runtime أكثر من 10 مليار دالة يومياً على الأجهزة حول العالم. أداء runtime يؤثر مباشرة على سرعة تشغيل التطبيق، سلاسة الرسوم المتحركة واستهلاك البطارية. كل استدعاء دالة، كل تخصيص ذاكرة وكل دورة جمع قمامة تمر عبر طبقة runtime.

نظام runtime: من أي مكونات يتكون

نظام runtime يتضمن خمسة مكونات رئيسية: محمل الفئات، مدير الذاكرة، مترجم أو مفسر، موزع الدوال ونظام الأمان. كل مكون يؤدي وظيفة محددة بدقة في عملية تنفيذ الكود.

محمل الفئات والتحقق

عندما يشغل المستخدم تطبيقاً، ClassLoader يحمل ملفات DEX (Android) أو ثنائيات Mach-O (iOS) إلى الذاكرة العشوائية. في Android، تشمل هذه المرحلة التحقق من البايت كود: يتحقق runtime من أن الكود لا يحتوي على تعليمات غير آمنة، لا يتجاوز حدود المصفوفات ويلتزم بالأنواع. التحقق هو خطوة أمان حاسمة تمنع تنفيذ الكود الضار.

مدير الذاكرة وجامع القمامة

مدير الذاكرة يخصص ويحرر الذاكرة للكائنات. في Android ART، يستخدم جامع قمامة متزامن مع جمع أجيالي: الكائنات الصغيرة تُفحص أكثر، الكبيرة أقل. Objective-C Runtime يستخدم Automatic Reference Counting (ARC)، حيث يدرج المترجم استدعاءات retain/release تلقائياً.

موزع الدوال والجدول الافتراضي

موزع الدوال يحدد أي تنفيذ للدالة سيتم استدعاؤه. في اللغات الثابتة (Kotlin, Swift)، يتم التوزيع عبر vtable — جدول الدوال الافتراضية. في اللغات الديناميكية (Objective-C)، تمر الرسالة عبر objc_msgSend، الذي يبحث عن التنفيذ في الفئة وفئاتها الفائقة. تُخزن النتيجة في method cache لتسريع الاستدعاءات المتكررة.

كيف يعمل ART على Android

Android Runtime (ART) هو آلة افتراضية تنفذ بايت كود DEX لتطبيقات Android. حل ART محل Dalvik في Android 5.0 Lollipop، مقدماً ترجمة AOT: يُترجم التطبيق إلى كود آلة مرة واحدة أثناء التثبيت. هذا أزال الحمل الزائد لترجمة JIT عند كل تشغيل.

بدءاً من Android 7.0 Nougat، يستخدم ART منهجاً هجيناً. أثناء التثبيت، يتم تنفيذ ترجمة JIT فقط للدوال كثيرة الاستخدام (hot methods)، باقي الكود يُفسر. عملية خلفية (profile-guided optimization) تحلل أي الدوال تُستدعى أكثر من غيرها وتترجمها AOT أثناء خمول الجهاز. هذا يقلص وقت التثبيت مع ضمان أداء عالٍ.

ART يشمل أيضاً مترجم AOT (dex2oat) الذي يحول ملفات DEX إلى ثنائيات ELF مع كود آلة ARM64. تتم الترجمة بثلاثة مستويات تحسين: quicken (سريع)، optimize (متوسط) و everything (كامل). افتراضياً، يستخدم Android optimize، الموازن بين سرعة الترجمة وأداء الكود.

kotlin
class RuntimeExample {
    fun measureExecutionTime() {
        val start = System.nanoTime()
        // استدعاء دالة مترجمة بواسطة ART
        processData()
        val end = System.nanoTime()
        println("وقت التنفيذ: ${end - start} نانوثانية")
    }
}

في المثال أعلاه، System.nanoTime() هي دالة أصلية يُوزع استدعاؤها عبر runtime ART إلى نواة Linux. ART يحول بايت كود Kotlin إلى تعليمات ARM64 ينفذها معالج الجهاز. هذه العملية تحدث بشفافية للمطور، لكن تحسينها مهمة رئيسية لفريق Android Platform.

Profile-Guided Optimization (PGO)

Profile-guided optimization هي آلية ART تجمع ملفات استخدام الدوال. ملف profiles/.primary.prof يحتوي على قائمة بالدوال hot التي تُترجم AOT. وفقاً لـ Android Performance Team، PGO تسرع تشغيل التطبيق بنسبة 15–30% بعد عدة أيام من الاستخدام، بمجرد تراكم الملف.

يمكن للمطور تفعيل baseline profiles في مشروع Gradle الخاص به. هي تعليقات يدوية تخبر ART أي الدوال تترجم AOT فوراً بعد التثبيت. baseline profiles تقلل أول تشغيل بنسبة 40% دون انتظار إنشاء الملف في الخلفية.

كيف يعمل Objective-C Runtime على iOS

Objective-C Runtime هي مكتبة ديناميكية توفر تنفيذ كود Objective-C على iOS و macOS. جوهرها هو دالة objc_msgSend، التي تنفذ تمرير الرسائل: بدلاً من استدعاء دالة مباشر، يرسل الكائن رسالة مع منتقي (selector)، ويحدد runtime أي تنفيذ يجب تشغيله.

كل كائن Objective-C يحتوي على مؤشر isa إلى فئته، والفئة تملك dispatch table تربط المنتقيات (SEL) بالتنفيذات (IMP). عندما تُستدعى دالة، objc_msgSend يجتاز السلسلة: فئة ← فئة فائقة ← NSObject، حتى يجد IMP. إذا لم يُعثر على تنفيذ، يستدعي runtime forwarding mechanism، الذي يمكنه اعتراض الرسالة أو توليد استثناء.

Objective-C Runtime يدعم أيضاً method swizzling — استبدال IMP لمنتقي موجود أثناء التنفيذ. هذه آلية قوية تُستخدم في مكتبات AOP وأدوات المراقبة، لكنها تتطلب حذراً بسبب تأثيرها على التطبيق بأكمله.

objective-c
@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

الكود يظهر وصولاً مباشراً إلى API Objective-C Runtime: objc_getClass يحصل على كائن الفئة بالاسم، class_copyMethodList يستخرج قائمة جميع الدوال. هذه هي التأمل (reflection) في العمل — الوصول إلى بيانات وصفية للفئة أثناء التنفيذ. هذا المنهج يُستخدم في XCTest للتسجيل الديناميكي للاختبارات.

مؤشر isa و tagged pointers

مؤشر isa هو مؤشر إلى فئة الكائن، مُخزن في أول 8 بايتات من كل كائن. بدءاً من iOS 12، أدخلت Apple تقنية isa-swizzling للتحسين: البتات السفلية من isa ترمز معلومات إضافية عن حالة الكائن. tagged pointers هي تحسين آخر حيث تُخزن القيم حتى 60 بت (NSNumber, NSDate) مباشرة في المؤشر، دون تخصيص كائن في الكومة. هذا يقلل حمل مدير الذاكرة بنسبة 30%.

ترجمة JIT مقابل AOT: مقارنة المناهج

JIT (Just-In-Time) و AOT (Ahead-Of-Time) هما منهجان لترجمة البايت كود إلى كود آلة. JIT يترجم الكود أثناء تنفيذ التطبيق، محلالاً النقاط الساخنة ومحسناً إياها أثناء العمل. AOT يترجم كل الكود مسبقاً — أثناء تثبيت التطبيق أو في جانب المطور.

الخاصيةJITAOT
وقت الترجمةأثناء التنفيذأثناء التثبيت/البناء
حجم APK/IPAأصغر (بايت كود فقط)أكبر (كود آلة)
سرعة التشغيلأقل (ترجمة مطلوبة)أعلى (كود جاهز)
التحسين حسب الجهازنعم (تكيفي)محدود (عام)
استهلاك RAMأعلى (مترجم في الذاكرة)أقل

المنهج الهجين لـ ART (Android 7+) يُعتبر مثالياً: يستخدم التطبيق مفسراً للدوال نادرة الاستدعاء، JIT للدوال hot و AOT للدوال من profile-guided optimization. iOS، على النقيض، يستخدم AOT صارماً عبر LLVM: Swift و Objective-C يُترجمان إلى كود آلة في مرحلة البناء في Xcode.

وفقاً لـ Apple Developer Documentation, 2024، Swift runtime يضيف حوالي 15 م.ب. إلى حجم التطبيق. Flutter يستخدم Dart VM الخاصة به، حيث تعمل ترجمة JIT في وضع التصحيح لإعادة التحميل السريع (hot reload)، و AOT في وضع الإصدار لأقصى أداء. React Native يستخدم Hermes — محرك JavaScript مع ترجمة AOT يقلل وقت التشغيل بنسبة 50%.

ARM64 Runtime وكود الآلة

ARM64 Runtime هو المستوى الذي يتفاعل فيه كود الآلة مع معالج الجهاز. معظم الأجهزة المحمولة الحديثة تعمل على معالجات ARM64 (aarch64). runtime يترجم البايت كود أو الاستدعاءات الأصلية إلى تعليمات ARM64 ينفذها CPU.

المسجلات الرئيسية لـ ARM64 التي يستخدمها runtime: x0–x7 (معاملات الدوال)، x8 (نتيجة غير مباشرة)، x30 (عنوان العودة)، sp (مؤشر الرصة)، fp (مؤشر الإطار). ART يولد كوداً يتبع ARM64 Procedure Call Standard: كل استدعاءات الدوال تمر عبر البروتوكول المحدد بهندسة المعالج.

فهم ABI ARM64 مهم لتحسين الأداء: التخزين المؤقت للاستدعاءات (inline caching)، توقع التفرع (branch prediction) ومحاذاة الكود في الذاكرة تؤثر مباشرة على سرعة runtime. أدوات التنميط (Android Studio Profiler, Instruments) تظهر أي أجزاء الكود تقضي معظم الوقت في runtime — تحسين هذه يعطي أكبر تحسن.

cpp
// مثال على تجميع ARM64 المولد بواسطة 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 على الأداء

الحمل الزائد لل runtime هو الثمن الحتمي للتوزيع الديناميكي. كل استدعاء دالة عبر runtime يتطلب: البحث عن التنفيذ في dispatch table، التحقق من الأنواع، استدعاء IMP وإرجاع النتيجة. القياسات تظهر أن runtime يضيف 10–50 نانوثانية لكل استدعاء في Objective-C و 5–20 نانوثانية في ART.

لتقليل الحمل الزائد، يستخدم المطورون monomorphic inlining (ART) و method caching (Objective-C). Kotlin/Native و Swift يُترجمان مباشرة إلى ARM64، مزيلين تماماً طبقة runtime، لكن مع فقدان الإمكانيات الديناميكية — التأمل (reflection)، swizzling، تحميل الفئات الديناميكي.

الأسئلة الشائعة

ما الفرق بين Runtime و SDK؟

SDK (Software Development Kit) هو مجموعة أدوات لتطوير التطبيق (مترجم، مكتبات، أدوات مساعدة). Runtime هو البيئة التي يُنفذ فيها التطبيق المطور على الجهاز. المطور يحتاج SDK، المستخدم يحتاج runtime.

هل يمكن استبدال Runtime في تطبيق محمول؟

لا — runtime جزء من نظام التشغيل ولا يمكن استبداله من قبل المستخدم. ART مدمج في Android Framework، Objective-C Runtime في iOS. يمكن للمطور اختيار اللغة (Kotlin/Native بدون runtime) أو استخدام آلات افتراضية مثل Dart VM في Flutter.

هل يؤثر Runtime على استهلاك البطارية؟

نعم، runtime يؤثر على استهلاك الطاقة. جمع القمامة في ART و Swift runtime يستخدمان CPU، مما يزيد استهلاك البطارية. التحسينات مثل concurrent GC و tagged pointers في iOS تقلل تأثير runtime على البطارية بنسبة 20–30%.

ما هو runtime error وكيف يتم اكتشافه؟

Runtime error هو خطأ يحدث أثناء التنفيذ: استثناء مؤشر فارغ، تجاوز حدود المصفوفة، قسمة على صفر. على عكس أخطاء وقت الترجمة، لا تُكتشف أثناء البناء. تُكتشف عبر كتل try-catch أو crash reporting (Firebase Crashlytics, Sentry).

كيف يختلف Swift runtime عن Objective-C Runtime؟

Swift runtime أخف من Objective-C: لا يدعم التوزيع الديناميكي افتراضياً، يستخدم value types (struct) دون تخصيص في الكومة ولا يحتوي على message forwarding. دوال Swift تُستدعى مباشرة عبر vtable ما لم تكن موسومة بـ @objc dynamic. هذا يعطي تحسناً في السرعة يصل إلى 5x في اختبارات الأداء.

الخلاصة

  • Runtime هو بيئة تنفيذ تدير الذاكرة والدوال وأمان الكود.
  • ART (Android) يستخدم منهجاً هجيناً JIT/AOT مع profile-guided optimization لأداء مثالي.
  • Objective-C Runtime مبني على تمرير الرسائل عبر objc_msgSend و dispatch table.
  • JIT يترجم الكود أثناء التشغيل ويتكيف مع الجهاز، AOT يترجم مسبقاً لتشغيل سريع.
  • ARM64 Runtime هو الطبقة العتادية التي تنفذ كود الآلة على المعالجات الحديثة.
  • الحمل الزائد لل runtime يتراوح بين 5–50 نانوثانية لكل استدعاء دالة ويُقلل بـ inlining و caching.
  • فهم runtime ضروري لتحسين الأداء، التصحيح واختيار هندسة التطبيق.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا