يفترض هذا المستند أنّك اتّبعت إرشادات أفضل الممارسات لتطبيقات Android ضمن إدارة الذاكرة، مثل إدارة ذاكرة تطبيقك.
مقدمة
تسرّب الذاكرة هو نوع من تسرّب الموارد يحدث عندما لا يحرّر برنامج الكمبيوتر الذاكرة المخصّصة التي لم يعُد بحاجة إليها. يمكن أن يؤدي التسريب إلى طلب التطبيق لمساحة ذاكرة من نظام التشغيل أكبر من المساحة المتاحة، وبالتالي تعطل التطبيق. هناك عدد من الممارسات غير الصحيحة التي يمكن أن تؤدي إلى تسرّب الذاكرة في تطبيقات Android، مثل عدم التخلص من الموارد بشكل صحيح أو عدم إلغاء تسجيل المستمعين عندما لا تكون هناك حاجة إليهم.
يقدّم لك هذا المستند بعض أفضل الممارسات لمساعدتك في منع تسرُّب الذاكرة ورصده وحلّه في الرمز البرمجي. إذا جرّبت الطرق الواردة في هذا المستند واشتبهت في حدوث تسرّب للذاكرة في حِزم تطوير البرامج (SDK)، يُرجى الاطّلاع على كيفية الإبلاغ عن المشاكل في حِزم تطوير البرامج (SDK) من Google.
قبل التواصل مع فريق الدعم
قبل الإبلاغ عن تسرّب الذاكرة إلى فريق الدعم في Google، يُرجى اتّباع أفضل الممارسات بالإضافة إلى خطوات تصحيح الأخطاء الواردة في هذا المستند للتأكّد من أنّ الخطأ ليس في الرمز البرمجي. قد تؤدي هذه الخطوات إلى حلّ مشكلتك، وإذا لم تنجح، ستؤدي إلى إنشاء المعلومات التي يحتاجها فريق الدعم في Google لمساعدتك.
منع تسرُّب الذاكرة
اتّبِع أفضل الممارسات التالية لتجنُّب بعض الأسباب الأكثر شيوعًا لتسرُّب الذاكرة في الرموز البرمجية التي تستخدم حِزم تطوير البرامج (SDK) من Google.
أفضل الممارسات لتطبيقات Android
تأكَّد من تنفيذ كل ما يلي في تطبيق Android:
- إلغاء حجز الموارد غير المستخدَمة
- إلغاء تسجيل المستمعين عندما لا تكون هناك حاجة إليهم
- إلغاء المهام عند عدم الحاجة إليها
- إعادة توجيه طرق مراحل النشاط لإخلاء الموارد
- استخدِم أحدث إصدارات حزم تطوير البرامج (SDK).
- تجنَّب حظر سلسلة التعليمات الرئيسية أثناء الإعداد لمنع حدوث أخطاء ANR.
للحصول على تفاصيل محدّدة حول كلّ من هذه الممارسات، يُرجى الاطّلاع على الأقسام التالية.
إلغاء حجز الموارد غير المُستخدَمة
عندما يستخدم تطبيق Android موردًا، تأكَّد من تحرير المورد عندما لم تعد هناك حاجة إليه. وإذا لم تفعل ذلك، سيستمر المورد في استهلاك الذاكرة حتى بعد انتهاء تطبيقك من استخدامه. لمزيد من المعلومات، يُرجى مراجعة مراحل النشاط في مستندات Android.
إصدار مراجع GoogleMap القديمة في حِزم تطوير البرامج (SDK) الجغرافية
من الأخطاء الشائعة أنّ GoogleMap يمكن أن يتسبّب في تسرّب الذاكرة إذا تم تخزينه مؤقتًا باستخدام NavigationView أو MapView. يتضمّن GoogleMap علاقة واحد لواحد مع NavigationView أو MapView الذي يتم استرداده منه. يجب إما التأكّد من عدم تخزين GoogleMap مؤقتًا أو من تحرير المرجع عند استدعاء NavigationView#onDestroy أو MapView#onDestroy. في حال استخدام NavigationSupportFragment أو MapSupportFragment أو الجزء الخاص بك الذي يلتف حول طرق العرض هذه، يجب إصدار المرجع في Fragment#onDestroyView.
class NavFragment : SupportNavigationFragment() {
var googleMap: GoogleMap?
override fun onCreateView(
inflater: LayoutInflater,
parent: ViewGroup?,
savedInstanceState: Bundle?,
): View {
super.onCreateView(inflater,parent,savedInstanceState)
getMapAsync{map -> googleMap = map}
}
override fun onDestroyView() {
googleMap = null
}
}
إلغاء تسجيل المستمعين عند عدم الحاجة إليهم
عندما يسجّل تطبيق Android أداة معالجة لحدث معيّن، مثل النقر على زر أو تغيير في حالة العرض، تأكَّد من إلغاء تسجيل أداة المعالجة عندما لا يحتاج التطبيق إلى مراقبة الحدث. إذا لم تفعل ذلك، ستستمر المستمعات في استهلاك الذاكرة حتى بعد انتهاء التطبيق منها.
على سبيل المثال، لنفترض أنّ تطبيقك يستخدم حزمة تطوير البرامج (SDK) للتنقّل ويستدعي
أداة معالجة الحدث التالية للاستماع إلى أحداث الوصول:
addArrivalListener
للاستماع إلى أحداث الوصول، يجب أيضًا استدعاء
removeArrivalListener
عندما لا يحتاج إلى مراقبة أحداث الوصول.
var arrivalListener: Navigator.ArrivalListener? = null
fun registerNavigationListeners() {
arrivalListener =
Navigator.ArrivalListener {
...
}
navigator.addArrivalListener(arrivalListener)
}
override fun onDestroy() {
navView.onDestroy()
if (arrivalListener != null) {
navigator.removeArrivalListener(arrivalListener)
}
...
super.onDestroy()
}
إلغاء المهام عند عدم الحاجة إليها
عندما يبدأ تطبيق Android مهمة غير متزامنة، مثل عملية تنزيل أو طلب شبكة، تأكَّد من إلغاء المهمة عند انتهائها. إذا لم يتم إلغاء المهمة، فستستمر في العمل في الخلفية حتى بعد انتهاء التطبيق منها.
لمزيد من التفاصيل حول أفضل الممارسات، يُرجى الاطّلاع على مقالة إدارة ذاكرة تطبيقك في مستندات Android.
إعادة توجيه طرق مراحل النشاط لتحرير الموارد
إذا كان تطبيقك يستخدم حزمة تطوير البرامج (SDK) لخدمة "التنقّل" أو "خرائط Google"، تأكَّد من تحرير الموارد من خلال إعادة توجيه طرق مراحل النشاط (الموضّحة بالخط العريض) إلى navView. يمكنك إجراء ذلك باستخدام NavigationView في حزمة تطوير البرامج للتنقّل أو MapView في حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" أو حزمة تطوير البرامج للتنقّل. يمكنك أيضًا استخدام SupportNavigationFragment أو
SupportMapFragment بدلاً من استخدام NavigationView وMapView مباشرةً،
على التوالي. تتعامل الأجزاء الداعمة مع إعادة توجيه طرق مراحل النشاط.
class NavViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
navView = ...
navView.onCreate(savedInstanceState)
...
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
navView.onSaveInstanceState(savedInstanceState)
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
navView.onTrimMemory(level)
}
/* Same with
override fun onStart()
override fun onResume()
override fun onPause()
override fun onConfigurationChanged(...)
override fun onStop()
override fun onDestroy()
*/
}
استخدام أحدث إصدارات حزم تطوير البرامج (SDK)
يتم تحديث حِزم تطوير البرامج (SDK) من Google باستمرار من خلال إضافة ميزات جديدة وإصلاح الأخطاء وإجراء تحسينات على الأداء. يُرجى الحرص على تحديث حِزم SDK في تطبيقك باستمرار للحصول على هذه الإصلاحات.
تجنُّب حظر سلسلة التعليمات الرئيسية أثناء الإعداد لمنع حدوث أخطاء ANR
عندما يحظر تطبيق سلسلة التعليمات الرئيسية لفترة طويلة جدًا، قد يتسبّب ذلك في حدوث خطأ "التطبيق لا يستجيب" (ANR). لمنع حدوث أخطاء ANR، يجب الحفاظ على خفة وزن طرق مراحل النشاط، مثل onCreate()، قدر الإمكان من خلال تأجيل المهام التي تستغرق وقتًا طويلاً أو تشغيلها خارج سلسلة التعليمات الرئيسية.
لتجنُّب أخطاء ANR المرتبطة بإعداد حزمة SDK:
- أنشِئ مثيل خريطة واحدًا فقط في كل مرة.
- قلِّل من العمل على سلسلة واجهة المستخدم قدر الإمكان أثناء إنشاء مثيل للخريطة.
تصحيح أخطاء تسرُّب الذاكرة
إذا استمر ظهور حالات تسرُّب الذاكرة بعد تنفيذ جميع الاقتراحات السابقة في هذا المستند، اتّبِع هذه العملية لتصحيح الأخطاء.
قبل البدء، يجب أن تكون على دراية بكيفية إدارة Android للذاكرة. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة نظرة عامة على إدارة الذاكرة في Android.
لتصحيح أخطاء تسرُّب الذاكرة، اتّبِع الخطوات التالية:
- أعِد عرض المشكلة. هذه الخطوة ضرورية لتصحيح الأخطاء.
- تحقَّق مما إذا كان استخدام الذاكرة متوقَّعًا. تأكَّد من أنّ الاستخدام المتزايد الذي يبدو أنّه تسرُّب ليس في الواقع الذاكرة المطلوبة لتشغيل تطبيقك.
- تصحيح الأخطاء على مستوى عالٍ: هناك العديد من الأدوات المساعدة التي يمكنك استخدامها لتصحيح الأخطاء. تساعد ثلاث مجموعات مختلفة من الأدوات العادية في تصحيح أخطاء الذاكرة في Android: "استوديو Android" وPerfetto وأدوات سطر أوامر Android Debug Bridge (adb).
- التحقّق من استخدام تطبيقك للذاكرة الحصول على لقطة لأجزاء من الذاكرة وتتبُّع عمليات تخصيص الذاكرة ثم تحليلها
- إصلاح تسرُّب الذاكرة
تتناول الأقسام التالية هذه الخطوات بالتفصيل.
الخطوة 1: إعادة إنشاء المشكلة
إذا لم تتمكّن من إعادة إنشاء المشكلة، فكِّر أولاً في السيناريوهات التي قد تؤدي إلى تسرّب الذاكرة. قد ينجح الانتقال مباشرةً إلى الاطّلاع على لقطة لأجزاء من الذاكرة، إذا كنت تعرف أنّه تمت إعادة إنشاء المشكلة. ومع ذلك، إذا حصلت على لقطة لأجزاء من الذاكرة عند بدء تشغيل التطبيق أو في وقت عشوائي آخر، فقد لا تكون قد فعّلت الشروط التي تؤدي إلى حدوث تسرُّب. ننصحك بتجربة سيناريوهات مختلفة عند محاولة إعادة إظهار المشكلة:
ما هي مجموعة الميزات التي تم تفعيلها؟
ما هو التسلسل المحدّد لإجراءات المستخدم التي تؤدي إلى حدوث التسرُّب؟
- هل حاولت تفعيل هذا التسلسل عدة مرات؟
ما هي حالات مراحل النشاط التي مرّ بها التطبيق؟
- هل حاولت إجراء عدة تكرارات من خلال حالات مختلفة لمراحل النشاط؟
تأكَّد من إمكانية إعادة إنشاء المشكلة في أحدث إصدار من حِزم تطوير البرامج (SDK). يُحتمَل أنّه تم حلّ المشكلة في إصدار سابق.
الخطوة 2: التحقّق مما إذا كان استخدام الذاكرة للتطبيق متوقّعًا
تتطلّب كل ميزة ذاكرة إضافية. عند تصحيح أخطاء سيناريوهات مختلفة، فكِّر في ما إذا كان هذا الاستخدام متوقّعًا أو إذا كان هناك تسرّب في الذاكرة. على سبيل المثال، بالنسبة إلى الميزات المختلفة أو مهام المستخدمين، يمكنك مراعاة الاحتمالات التالية:
من المحتمل أن يكون هناك تسرُّب: يؤدي تفعيل السيناريو من خلال تكرارات متعددة إلى زيادة في استخدام الذاكرة بمرور الوقت.
استخدام الذاكرة المتوقّع على الأرجح: تتم استعادة الذاكرة بعد إيقاف السيناريو.
استخدام الذاكرة المتوقّع: يزداد استخدام الذاكرة لفترة من الوقت ثم يتناقص، وقد يرجع ذلك إلى ذاكرة تخزين مؤقت محدودة أو استخدام آخر متوقّع للذاكرة.
إذا كان سلوك التطبيق هو استخدام الذاكرة المتوقّع على الأرجح، يمكن حلّ المشكلة من خلال إدارة ذاكرة التطبيق. للحصول على مساعدة، يُرجى الاطّلاع على مقالة إدارة ذاكرة تطبيقك.
الخطوة 3: تصحيح الأخطاء بشكل عام
عند تصحيح أخطاء تسرُّب الذاكرة، ابدأ من مستوى عالٍ، ثم تعمَّق في التفاصيل بعد حصر الاحتمالات. استخدِم إحدى أدوات تصحيح الأخطاء العالية المستوى هذه لتحليل ما إذا كان هناك تسرُّب بمرور الوقت:
محلّل الذاكرة في "استوديو Android" (يُنصح به)
محلّل الذاكرة في "استوديو Android"
توفّر لك هذه الأداة مدرّجًا تكراريًا مرئيًا للذاكرة المستهلَكة. ويمكن أيضًا تفعيل اللقطات لأجزاء من الذاكرة وتتبُّع عمليات التخصيص من هذه الواجهة نفسها. هذه الأداة هي الاقتراح التلقائي. لمزيد من المعلومات، يُرجى الاطّلاع على محلّل الذاكرة في "استوديو Android".
عدّادات الذاكرة في Perfetto
تمنحك أداة Perfetto تحكّمًا دقيقًا في تتبُّع عدة مقاييس وتعرضها كلها في مدرّج تكراري واحد. لمزيد من المعلومات، يُرجى الاطّلاع على عدّادات الذاكرة في Perfetto.

أدوات سطر الأوامر في Android Debug Bridge (adb)
يتوفّر أيضًا جزء كبير مما يمكنك تتبُّعه باستخدام Perfetto كأداة سطر أوامر adb يمكنك الاستعلام عنها مباشرةً. هناك مثالان مهمان هما:
تتيح لك أداة Meminfo الاطّلاع على معلومات مفصّلة عن الذاكرة في وقت معيّن.
توفّر أداة Procstats بعض الإحصاءات المجمّعة المهمة بمرور الوقت.
من الإحصاءات المهمة التي يجب الاطّلاع عليها هنا الحد الأقصى لاستهلاك الذاكرة الفعلية (maxRSS) الذي يتطلّبه التطبيق بمرور الوقت. قد لا يكون MaxPSS دقيقًا. للاطّلاع على طريقة لزيادة الدقة، يُرجى مراجعة العلامة adb shell dumpsys procstats --help –start-testing.
تتبُّع التخصيص
يحدّد تتبُّع التخصيص تتبُّع تسلسل استدعاء الدوال البرمجية حيث تم تخصيص الذاكرة وإذا لم يتم تفريغها. هذه الخطوة مفيدة بشكل خاص عند تتبُّع حالات تسرُّب الذاكرة في الرموز البرمجية الأصلية. بما أنّ هذه الأداة تحدّد تتبع تسلسل استدعاء الدوال البرمجية، يمكن أن تكون وسيلة رائعة لتصحيح الأخطاء بسرعة في السبب الأساسي أو لمعرفة كيفية إعادة إنشاء المشكلة. للاطّلاع على خطوات استخدام ميزة تتبُّع عمليات التخصيص، يُرجى الاطّلاع على مقالة تصحيح أخطاء الذاكرة في الرموز البرمجية الأصلية باستخدام ميزة تتبُّع عمليات التخصيص.
الخطوة 4: التحقّق من استخدام تطبيقك للذاكرة من خلال لقطة لأجزاء من الذاكرة
يمكنك رصد تسرُّب الذاكرة من خلال الحصول على لقطة لأجزاء من الذاكرة في تطبيقك ثم فحصها بحثًا عن أي تسرُّبات. لقطة أجزاء من الذاكرة هي لقطة لجميع العناصر في ذاكرة التطبيق. ويمكن استخدامها لتشخيص تسرُّب الذاكرة والمشاكل الأخرى المتعلقة بالذاكرة.
يمكن لـ استوديو Android رصد حالات تسرّب الذاكرة التي لا يمكن لـ GC إصلاحها. عند التقاط لقطة لأجزاء من الذاكرة، يتحقّق "استوديو Android" مما إذا كان هناك نشاط أو جزء لا يزال من الممكن الوصول إليه ولكن تم تدميره بالفعل.
- التقاط لقطة لأجزاء من الذاكرة
- تحليل لقطة لأجزاء من الذاكرة للعثور على تسرُّبات الذاكرة
- إصلاح تسرُّب الذاكرة
لمعرفة التفاصيل، يُرجى الاطّلاع على الأقسام التالية.
تسجيل لقطة لأجزاء من الذاكرة
لأخذ لقطة لأجزاء من الذاكرة، يمكنك استخدام أداة Android Debug Bridge (adb) أو "محلّل الذاكرة" في "استوديو Android".
استخدام adb لالتقاط أجزاء من الذاكرة
لأخذ لقطة لأجزاء من الذاكرة باستخدام adb، اتّبِع الخطوات التالية:
- وصِّل جهاز Android بالكمبيوتر.
- افتح موجِّه الأوامر وانتقِل إلى الدليل الذي يتضمّن أدوات adb.
لأخذ لقطة لأجزاء من الذاكرة، نفِّذ الأمر التالي :
adb shell am dumpheap my.app.name $PHONE_FILE_OUTلاسترداد لقطة لأجزاء من الذاكرة، نفِّذ الأمر التالي:
adb pull $PHONE_FILE_OUT $LOCAL_FILE.
استخدام "استوديو Android" لالتقاط أجزاء من الذاكرة
لأخذ لقطة لأجزاء من الذاكرة باستخدام "محلّل الذاكرة" في "استوديو Android"، يُرجى اتّباع الخطوات الواردة في قسم أخذ لقطة لأجزاء من الذاكرة في Android.
تحليل لقطة لأجزاء من الذاكرة للعثور على تسرُّبات الذاكرة
بعد الحصول على لقطة لأجزاء من الذاكرة، يمكنك استخدام "محلّل الذاكرة" في "استوديو Android" لتحليلها. لإجراء هذا، اتبع هذه الخطوات:
افتح مشروع Android في "استوديو Android".
انقر على تشغيل (Run)، ثم اختَر إعدادات تصحيح الأخطاء (Debug).
افتح علامة التبويب Android Profiler.
انقر على الذاكرة.
انقر على فتح لقطة لأجزاء من الذاكرة واختَر ملف اللقطة الذي أنشأته. يعرض محلّل الذاكرة رسمًا بيانيًا لاستخدام تطبيقك للذاكرة.
استخدِم الرسم البياني لتحليل لقطة أجزاء من الذاكرة:
تحديد العناصر التي لم تعُد مستخدَمة
تحديد العناصر التي تستهلك قدرًا كبيرًا من الذاكرة
اطّلِع على مقدار الذاكرة التي يستخدمها كل عنصر.
استخدِم هذه المعلومات لتضييق نطاق تسرّب الذاكرة أو العثور على مصدره وإصلاحه.
الخطوة 5: إصلاح تسرُّب الذاكرة
بعد تحديد مصدر تسرّب الذاكرة، يمكنك إصلاحه. يساعد إصلاح تسرُّبات الذاكرة في تطبيقات Android في تحسين أداء تطبيقاتك واستقرارها. تختلف التفاصيل حسب السيناريو. ومع ذلك، يمكن أن تساعدك الاقتراحات التالية:
تأكَّد من أنّ تطبيقك يخصّص الذاكرة ويُلغي تخصيصها على النحو المقترَح في موضوع Android إدارة ذاكرة تطبيقك.
أزِل الرموز أو الموارد غير المستخدَمة من تطبيقك. للاطّلاع على تفاصيل حول تطبيقات Android، يُرجى مراجعة أفضل الممارسات لتطبيقات Android.
أدوات أخرى لتصحيح الأخطاء
بعد اكتمال هذه الخطوات، إذا لم تكن قد عثرت على تسرّب الذاكرة وأصلحته، فجرّب هذه الأدوات:
- تصحيح أخطاء الذاكرة في الرموز البرمجية الأصلية باستخدام ميزة تتبُّع عمليات التخصيص
- تحديد حالات تسرُّب الذاكرة باستخدام LeakCanary:
تصحيح أخطاء الذاكرة في الرموز البرمجية الأصلية باستخدام ميزة تتبُّع التخصيص
حتى إذا لم تكن تستخدم الرموز البرمجية الأصلية بشكل مباشر، فإنّ العديد من مكتبات Android الشائعة تستخدمها، بما في ذلك حِزم تطوير البرامج (SDK) من Google. إذا كنت تعتقد أنّ تسرّب الذاكرة يحدث في الرموز البرمجية الأصلية، هناك عدة أدوات يمكنك استخدامها لتصحيح الأخطاء. يُعدّ تتبُّع عمليات التخصيص باستخدام استوديو Android أو heapprofd (المتوافق أيضًا مع Perfetto) طريقة رائعة لتحديد الأسباب المحتملة لتسرُّب الذاكرة، وغالبًا ما يكون أسرع طريقة لتصحيح الأخطاء.
تتميز ميزة "تتبُّع عمليات التخصيص" أيضًا بأنّها تتيح لك مشاركة النتائج بدون تضمين معلومات حسّاسة يمكن العثور عليها في الذاكرة الديناميكية.
تحديد حالات تسرُّب الذاكرة باستخدام LeakCanary
LeakCanary هي أداة فعّالة لتحديد تسرُّبات الذاكرة في تطبيقات Android. لمزيد من المعلومات حول كيفية استخدام LeakCanary في تطبيقك، يُرجى الانتقال إلى LeakCanary.
كيفية الإبلاغ عن مشاكل في حِزم تطوير البرامج (SDK) من Google
إذا جرّبت الطرق الواردة في هذا المستند وكنت تشكّ في حدوث تسرُّب للذاكرة في حِزم تطوير البرامج (SDK)، يُرجى التواصل مع فريق دعم العملاء وتقديم أكبر قدر ممكن من المعلومات التالية:
خطوات إعادة إنشاء تسرُّب الذاكرة إذا كانت الخطوات تتطلّب ترميزًا معقّدًا، قد يكون من المفيد نسخ الرمز الذي يكرّر المشكلة في نموذج التطبيق وتقديم خطوات إضافية يجب اتّخاذها في واجهة المستخدم لتشغيل التسريب.
لقطات لأجزاء من الذاكرة تم التقاطها من تطبيقك مع إعادة إنشاء المشكلة التقِط لقطات لأجزاء من الذاكرة في نقطتَين زمنيتَين مختلفتَين تُظهران أنّ استخدام الذاكرة قد زاد بمقدار كبير.
في حال توقُّع حدوث تسرُّب في الذاكرة الأصلية، يمكنك مشاركة مخرجات تتبُّع عمليات التخصيص من heapprofd.
تقرير خطأ تم إنشاؤه بعد إعادة إنشاء حالة التسرُّب
تتبُّع تسلسل استدعاء الدوال البرمجية لأي أعطال متعلقة بالذاكرة
ملاحظة مهمة: لا تكفي عادةً عمليات تتبُّع تسلسل استدعاء الدوال البرمجية وحدها لتصحيح أخطاء الذاكرة، لذا يُرجى التأكّد من تقديم أحد أشكال المعلومات الأخرى أيضًا.