إدارة الذاكرة

السؤال الأول الذي يطرحه معظم مطوري Java هو كيف يتم تنفيذ إدارة الذاكرة بواسطة J2ObjC، نظرًا لأن Java بها مجموعة البيانات غير الصالحة ولا يتم تنفيذ FALSE-C افتراضيًا. يتميّز نظام التشغيل iOS بطريقتين لإدارة الذاكرة: احتساب المراجع والاحتساب التلقائي للمراجع (ARC).

ينشئ J2ObjC رمزًا مختلفًا لإدارة الذاكرة، بناءً على الطريقة التي يتم اختيارها. الترجمة من خلال الخيار -use-arc لإنشاء رمز يستخدم تقنية "وقت تشغيل التطبيقات في Chrome" وتستخدم تلقائيًا الاحتساب اليدوي للمراجع.

احتساب المراجع

توضّح طريقة احتساب المراجع ملكية العناصر بوضوح. تمتلك الطريقة كائنًا عند إنشائه، حتى تطلق هذا الكائن. عند استلام كائن من طريقة أخرى، تحتفظ طريقة الاستلام بالكائن إذا كانت هناك حاجة للرجوع إليه بعد إرجاع الطريقة. عندما لا تحتاج إحدى الطرق إلى الإشارة إلى كائن، يجب تحريره. عندما يكون عدد مرات الاحتفاظ بالكائن صفرًا، يتم تحرير ذاكرته ويصبح الكائن غير صالح. عندما يتم تحرير الكائنات، يتم استدعاء طريقة disloc() الخاصة بها إلى إطلاق ملكية متغيرات المثيل الخاصة بها.

تتمثل إحدى مشاكل هذا الأسلوب في كيفية نقل ملكية أحد العناصر. على سبيل المثال، قد يتم استدعاء طريقة المصنع لإنشاء كائن. إذا أفرغت الطريقة الأصلية الكائن قبل إعادته (لأنه لم يعد يريد امتلاك الكائن)، يتم إلغاء تحرير هذا الكائن قبل أن تتمكن طريقة الاستدعاء من الاحتفاظ به.

لنقل ملكية عنصر، ترسل إحدى الطرق إليه رسالة إصدار تلقائي (بدلاً من رسالة إصدار) تؤدي إلى تأجيل رسالة الإصدار. يتيح ذلك لطريقة المصنع إنشاء كائن لإرجاعه والتنازل عن ملكيته بدون إلغاء الكائن. على فترات زمنية منتظمة (مثل ما يحدث بعد كل تكرار لتكرار حدث في تطبيق iOS)، يتم "استنزاف" مجمّع الإصدار التلقائي، ما يعني إرسال رسائل الإصدار المؤجلة إلى جميع الكائنات في هذه المجموعة. ويتم إطلاق أي كائنات تقل أعدادها المتبقية إلى صفر كالمعتاد.

ولأنّ أعباء إدارة الذاكرة تقع على عاتق المطوّر، فإنّه من السهل تسريب الذاكرة باستخدام طريقة احتساب المراجع. ومع ذلك، تنصح شركة Apple باتّباع بعض أفضل الممارسات للحدّ من هذه المشكلة، وهي تنفّذها شركة J2ObjC.

كما يتم توفير وقت التشغيل والأدوات اللازمة للكشف عن تسرُّب الذاكرة. يُبلغ وقت تشغيل Goal-C عن أي تسرّب تم اكتشافه عند الخروج من أحد التطبيقات، وهو أحد الأسباب التي تجعل J2ObjC يحوّل اختبارات JUnit إلى برامج ثنائية قابلة للتنفيذ. يستخدم Xcode لغة Clang، ويحتوي هذا المحول البرمجي على تحليل ثابت ممتاز لمشكلات الذاكرة، والتي توفرها Xcode باستخدام الأمر Analyze الخاص بها.

الاحتساب التلقائي للمراجع (ARC)

إنّ ARC هي طريقة إدارة الذاكرة التي تنصح بها Apple. فهو ينقل مسؤولية احتساب المراجع إلى المحوّل، ما يضيف الطرق المناسبة للاحتفاظ بالبيانات وإصدارها وإطلاقها تلقائيًا أثناء التجميع. يدعم ARC المراجع الضعيفة للأجهزة التي تعمل بنظام التشغيل iOS 5 والإصدارات الأحدث.

ننصحك باستخدام تقنية "وقت تشغيل التطبيقات في Chrome" في المشاريع للرموز المترجَمة. تشبه كود Object-C المكتوب بخط اليد كود Goal-C. ويمكن أن يساعد استخدام تقنية "وقت تشغيل التطبيقات في Chrome" المطوّرين في تجنُّب الأخطاء الشائعة المتعلقة بالذاكرة، مثل المبالغة في إصدار المحتوى أو انخفاض القيمة، ما يجعل عملية إدارة الذاكرة أبسط وأقل عرضة للأخطاء.

تجدر الإشارة إلى أنّ نظام ARC ليس آمنًا باستخدام بعض أنواع الاستثناء تلقائيًا. على وجه التحديد، تسرب الذاكرة عند طرح استثناءات. نظرًا لأن الاستثناءات أكثر شيوعًا في Java وعادة ما يمكن استردادها، فقد يكون هذا مشكلة. سيؤدي استخدام -fobjc-arc-exceptions عند التحويل باستخدام قوس إلى إصلاح التسريبات بتكلفة أداء مقبولة.

ننصح أيضًا بأن تستخدم المشاريع الجديدة تقنية "وقت تشغيل التطبيقات في Chrome" لرمز FALSE-C المكتوب بخط اليد، وأن تتراجع فقط عن الاحتساب اليدوي للمراجع إذا كان تحليل البيانات يعرض مشكلة في الأداء. يمكن تجميع كل من التعليمات البرمجية ARC والرموز غير التابعة لها وربطها في التطبيق نفسه بدون مشكلة.

المراجع الضعيفة

يمكن إضافة تعليقات توضيحية إلى الحقول باستخدام com.google.devtools.j2objc.Weak، الذي تستخدمه أداة الترجمة لإنشاء حقول تتّبع دلالات المرجع الضعيف لـ FALSE-C. وعند استخدام حساب المراجع، يعني ذلك أنّه لا يتم الاحتفاظ بالحقل عند إعداده، بل يتم إطلاقه تلقائيًا عند إصدار المثيل الذي يتضمّنه. مع ARC، يتم تمييز الحقول الضعيفة بالتعليق التوضيحي __unsafe_unretained، ويتم تصنيف السمات ذات الصلة بأنّها ضعيفة.

في بعض الحالات، يدخل مثيل الفئة الداخلية في دورة مرجعية مع مثيله الخارجي. هنا، يتم استخدام التعليق التوضيحي com.google.devtools.j2objc.WeakOuter لتمييز الفئة الداخلية، وبالتالي يتم التعامل مع الإشارة إلى الفئة الخارجية على النحو الموضَّح أعلاه. لا تتأثر الحقول الأخرى في الفئة الداخلية بهذا التعليق التوضيحي.

يتوافق J2ObjC أيضًا مع الفئة WeakReference، لذا سيعمل رمز Java الذي تستخدمه بطريقة واحدة عند الترجمة. عليك الانتباه إلى أنّ WeakReference غير محدد بطبيعته في JVM، ولذلك فإنّ التطبيقات التي تريد تجنُّب تسرُّب الذاكرة مع الحفاظ على إمكانية التوقّع يجب أن تفضّل @Weak و@WeakOuter بدلاً من ذلك.

أدوات إدارة الذاكرة