يفترض هذا المستند أنّك اتّبعت إرشادات أفضل الممارسات لتطبيقات Android في ما يتعلّق بإدارة الذاكرة، مثل إدارة ذاكرة تطبيقك.
مقدمة
تسريب الذاكرة هو نوع من تسريب الموارد يحدث عندما لا يحرر برنامج الكمبيوتر الذاكرة المخصّصة التي لم يعُد بحاجة إليها. يمكن أن يؤدي تسرُّب الذاكرة إلى طلب التطبيق المزيد من الذاكرة من نظام التشغيل أكثر مما هو متاح، وبالتالي تعطُّل التطبيق. يمكن أن تؤدي بعض الممارسات غير السليمة إلى حدوث تسرُّب للذاكرة في تطبيقات Android، مثل عدم التخلص من الموارد بشكل صحيح أو عدم إلغاء تسجيل أدوات معالجة الأحداث عند عدم الحاجة إليها.
يقدّم لك هذا المستند بعض أفضل الممارسات للمساعدة في منع رصد مشاكل تسرُّب الذاكرة وحلّها في الرمز البرمجي. إذا جرّبت الطرق الواردة في هذا المستند وكنت تشك في حدوث تسرُّب للذاكرة في حِزم SDK، يمكنك الاطّلاع على كيفية الإبلاغ عن مشاكل في حِزم SDK من Google.
قبل التواصل مع فريق الدعم
قبل الإبلاغ عن تسرُّب الذاكرة إلى فريق الدعم في Google، اتّبِع أفضل الممارسات وخطوات تصحيح الأخطاء الواردة في هذا المستند للتأكّد من أنّ الخطأ ليس في الرمز البرمجي. قد تساعد هذه الخطوات في حلّ مشكلتك، وإذا لم تفعل ذلك، ستنشئ المعلومات التي يحتاجها فريق الدعم في Google لمساعدتك.
منع تسرُّبات الذاكرة
اتّبِع أفضل الممارسات التالية لتجنُّب بعض الأسباب الأكثر شيوعًا لتسرُّب الذاكرة في الرموز البرمجية التي تستخدم حِزم تطوير البرامج (SDK) من Google.
أفضل الممارسات لتطبيقات Android
تأكَّد من تنفيذ جميع ما يلي في تطبيق Android:
- إلغاء حجز الموارد غير المستخدَمة
- إلغاء تسجيل أدوات معالجة الأحداث عندما لا يعود هناك حاجة إليها
- إلغاء المهام عند عدم الحاجة إليها
- توجيه طرق مراحل النشاط إلى الأمام لإتاحة الموارد
- استخدام أحدث إصدارات حِزم تطوير البرامج (SDK)
للحصول على تفاصيل محدّدة حول كلّ من هذه الممارسات، يُرجى الاطّلاع على الأقسام التالية.
إلغاء حجز الموارد غير المستخدَمة
عندما يستخدم تطبيق Android أحد الموارد، احرص على تحرير هذا المورد عندما لا يعود هناك حاجة إليه. وفي حال عدم إجراء ذلك، سيستمر العنصر في استهلاك الذاكرة حتى بعد أن ينتهي تطبيقك من استخدامه. لمزيد من المعلومات، راجِع دورة حياة النشاط في مستندات Android.
إصدار مراجع GoogleMap قديمة في GeoSDKs
من الأخطاء الشائعة أنّ 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) الخاصة بخدمة Navigation، وأنّه يستدعي أداة معالجة الأحداث التالية للاستماع إلى أحداث الوصول:
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 في تطبيقك لتلقّي هذه الإصلاحات.
تصحيح أخطاء تسرّب الذاكرة
إذا استمر ظهور تسريبات الذاكرة بعد تنفيذ جميع الاقتراحات السارية الواردة سابقًا في هذا المستند، اتّبِع الخطوات التالية لتصحيح الأخطاء.
قبل البدء، يجب أن تكون على دراية بكيفية إدارة Android للذاكرة. للحصول على معلومات، يُرجى قراءة نظرة عامة على إدارة الذاكرة في Android.
لتصحيح أخطاء تسرُّب الذاكرة، اتّبِع الخطوات التالية:
- أعِد إظهار المشكلة. هذه الخطوة ضرورية لتصحيح الأخطاء.
- تحقَّق مما إذا كان استخدام الذاكرة متوقعًا. تأكَّد من أنّ الاستخدام المتزايد الذي يبدو أنّه تسريب ليس في الواقع مقدار الذاكرة المطلوب لتشغيل تطبيقك.
- تصحيح الأخطاء على مستوى عالٍ: تتوفّر العديد من الأدوات المساعدة التي يمكنك استخدامها لتصحيح الأخطاء. تساعد ثلاث مجموعات أدوات مختلفة في تصحيح أخطاء الذاكرة في Android، وهي: "استوديو Android" وPerfetto وأدوات سطر الأوامر في Android Debug Bridge (adb).
- التحقّق من استخدام تطبيقك للذاكرة احصل على تفريغ الذاكرة المؤقتة وتتبُّع التخصيص ثم حلِّلهما.
- إصلاح تسربات الذاكرة
تتناول الأقسام التالية هذه الخطوات بالتفصيل.
الخطوة 1: إعادة عرض المشكلة
إذا لم تتمكّن من إعادة إنشاء المشكلة، عليك أولاً التفكير في السيناريوهات التي قد تؤدي إلى تسرُّب الذاكرة. قد يكون من المفيد الانتقال مباشرةً إلى فحص تفريغ الذاكرة المؤقتة إذا كنت تعرف أنّه تمت إعادة إنشاء المشكلة. ومع ذلك، إذا حصلت على تفريغ الذاكرة المؤقتة عند بدء تشغيل التطبيق أو في وقت عشوائي آخر، قد لا تكون قد فعّلت الشروط التي تؤدي إلى حدوث تسرُّب. ننصحك بتجربة سيناريوهات مختلفة عند محاولة إعادة إظهار المشكلة:
ما هي مجموعة الميزات التي يتم تفعيلها؟
ما هو التسلسل المحدّد لإجراءات المستخدم الذي يؤدي إلى حدوث التسريب؟
- هل جرّبت تكرارات متعددة لتفعيل هذه السلسلة؟
ما هي حالات دورة الحياة التي مرّ بها التطبيق؟
- هل جرّبت تكرارات متعددة من خلال حالات مختلفة لدورة الحياة؟
تأكَّد من إمكانية إعادة إنشاء المشكلة في أحدث إصدار من حِزم SDK. يُحتمَل أنّه تم حلّ المشكلة في إصدار سابق.
الخطوة 2: التحقّق مما إذا كان استخدام الذاكرة للتطبيق متوقعًا
تتطلّب كل ميزة ذاكرة إضافية. عند تصحيح أخطاء سيناريوهات مختلفة، عليك مراعاة ما إذا كان هذا الاستخدام متوقّعًا أم أنّه في الواقع تسرُّب للذاكرة. على سبيل المثال، بالنسبة إلى الميزات أو مهام المستخدمين المختلفة، ضع في اعتبارك الاحتمالات التالية:
من المحتمل حدوث تسرّب: يؤدي تفعيل السيناريو من خلال تكرارات متعددة إلى زيادة استخدام الذاكرة بمرور الوقت.
الاستخدام المتوقّع للذاكرة على الأرجح: تتم استعادة الذاكرة بعد إيقاف السيناريو.
الاستخدام المتوقّع للذاكرة: يزداد استخدام الذاكرة لفترة من الوقت ثم ينخفض تدريجيًا، وقد يرجع ذلك إلى ذاكرة تخزين مؤقت محدودة أو استخدام متوقّع آخر للذاكرة.
إذا كان سلوك التطبيق هو الاستخدام المتوقّع للذاكرة، يمكن حلّ المشكلة من خلال إدارة ذاكرة التطبيق. للحصول على المساعدة، اطّلِع على إدارة ذاكرة تطبيقك.
الخطوة 3: تصحيح الأخطاء على مستوى عالٍ
عند تصحيح خطأ تسريب الذاكرة، ابدأ بمستوى عالٍ، ثم انتقِل إلى مستوى أدنى بعد تضييق نطاق الاحتمالات. استخدِم إحدى أدوات تصحيح الأخطاء العالية المستوى التالية لتحليل ما إذا كان هناك تسرُّب بمرور الوقت:
أداة Memory Profiler في "استوديو 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 Studio تسريبات الذاكرة التي لا يمكن إصلاحها من خلال أداة GC. عند تسجيل تفريغ الذاكرة المؤقتة، يتحقّق "استوديو Android" مما إذا كان هناك نشاط أو جزء لا يزال يمكن الوصول إليه ولكن تم إتلافه بالفعل.
لمعرفة التفاصيل، يُرجى الاطّلاع على الأقسام التالية.
تسجيل لقطة لأجزاء من الذاكرة
لتسجيل نَسْخ ذاكرة، يمكنك استخدام Android Debug Bridge (adb) أو أداة Android Studio Memory Profiler.
استخدام 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".
انقر على تشغيل، ثم اختَر إعدادات تصحيح الأخطاء.
افتح علامة التبويب Android Profiler.
انقر على ذكريات.
اختَر فتح تفريغ الذاكرة المؤقتة واختَر ملف تفريغ الذاكرة المؤقتة الذي أنشأته. تعرض أداة تحليل استخدام الذاكرة رسمًا بيانيًا لاستخدام تطبيقك للذاكرة.
استخدِم الرسم البياني لتحليل تفريغ الذاكرة المؤقتة:
تحديد العناصر التي لم يعُد يتم استخدامها
تحديد العناصر التي تستهلك الكثير من الذاكرة
الاطّلاع على حجم الذاكرة التي يستخدمها كل عنصر
استخدِم هذه المعلومات لتضييق نطاق البحث عن مصدر تسرُّب الذاكرة أو العثور عليه وحلّه.
الخطوة 5: إصلاح تسربات الذاكرة
بعد تحديد مصدر تسرُّب الذاكرة، يمكنك إصلاحه. يساعد إصلاح تسريبات الذاكرة في تطبيقات Android على تحسين أداء تطبيقاتك وثباتها. تختلف التفاصيل حسب السيناريو. في المقابل، يمكن أن تساعدك الاقتراحات التالية:
تأكَّد من أنّ تطبيقك يخصّص الذاكرة ويزيل تخصيصها على النحو الموصى به في موضوع Android إدارة ذاكرة تطبيقك.
أزِل الرموز أو الموارد غير المستخدَمة من تطبيقك. وللحصول على تفاصيل حول تطبيقات Android، اطّلِع على أفضل الممارسات لتطبيقات Android.
أدوات تصحيح الأخطاء الأخرى
بعد إكمال هذه الخطوات، إذا لم تتمكّن من العثور على تسرب الذاكرة وإصلاحه، جرِّب الأدوات التالية:
- تصحيح أخطاء الذاكرة في الرمز البرمجي الأصلي باستخدام ميزة "تتبُّع عمليات التخصيص"
- تحديد عمليات تسريب الذاكرة باستخدام LeakCanary
تصحيح أخطاء الذاكرة في الرمز البرمجي الأصلي باستخدام ميزة "تتبُّع عمليات التخصيص"
حتى إذا كنت لا تستخدم الرمز البرمجي الأصلي مباشرةً، فإنّ العديد من مكتبات Android الشائعة تستخدمه، بما في ذلك حِزم تطوير البرامج (SDK) من Google. إذا كنت تعتقد أنّ تسريب الذاكرة يحدث في الرمز البرمجي الأصلي، تتوفّر عدة أدوات يمكنك استخدامها لتصحيح الأخطاء. يُعدّ تتبُّع عمليات التخصيص باستخدام استوديو Android أو heapprofd (متوافق أيضًا مع Perfetto) طريقة رائعة لتحديد الأسباب المحتملة لتسرُّب الذاكرة، كما أنّه غالبًا ما يكون أسرع طريقة لتصحيح الأخطاء.
تتميّز ميزة تتبُّع التخصيص أيضًا بأنّها تتيح لك مشاركة النتائج بدون تضمين معلومات حساسة يمكن العثور عليها في الذاكرة المؤقتة.
تحديد تسريبات الذاكرة باستخدام LeakCanary
LeakCanary هي أداة فعّالة لتحديد تسربات الذاكرة في تطبيقات Android. لمزيد من المعلومات حول كيفية استخدام LeakCanary في تطبيقك، يُرجى الانتقال إلى LeakCanary.
كيفية الإبلاغ عن مشاكل في حِزم تطوير البرامج (SDK) من Google
إذا جرّبت الطرق الواردة في هذا المستند وكنت تشك في حدوث تسرّب للذاكرة في حِزم SDK، يُرجى التواصل مع فريق دعم العملاء وتضمين أكبر قدر ممكن من المعلومات التالية:
خطوات إعادة إنشاء تسرُّب الذاكرة إذا كانت الخطوات تتطلّب ترميزًا معقّدًا، قد يكون من المفيد نسخ الرمز الذي يعيد إنتاج المشكلة في تطبيقنا النموذجي وتقديم خطوات إضافية يجب اتّخاذها في واجهة المستخدم لتفعيل تسرُّب الذاكرة.
عمليات تفريغ الذاكرة المؤقتة التي تم تسجيلها من تطبيقك بعد إعادة إنشاء المشكلة التقط عمليات تفريغ لذاكرة التخزين المؤقت في وقتَين مختلفَين يوضّحان أنّ استخدام الذاكرة قد زاد بشكل كبير.
في حال توقُّع حدوث تسرُّب للذاكرة الأصلية، شارِك ناتج تتبُّع عملية التخصيص من heapprofd.
تقرير خطأ تم تسجيله بعد إعادة إنشاء حالة التسريب
تتبُّع تسلسل استدعاء الدوال البرمجية لأي أعطال مرتبطة بالذاكرة
ملاحظة مهمة: لا تكفي عمليات تتبُّع تسلسل استدعاء الدوال البرمجية عادةً لتصحيح خطأ متعلّق بالذاكرة، لذا احرِص على تقديم أحد أشكال المعلومات الأخرى أيضًا.