يفترض هذا المستند أنّك اتّبعت إرشادات أفضل الممارسات لتطبيقات Android ضمن إدارة الذاكرة، مثل إدارة ذاكرة تطبيقك.
مقدمة
تسرُّب الذاكرة هو نوع من تسرُّب الموارد الذي يحدث عندما لا يُفرِج أحد برامج الكمبيوتر عن الذاكرة المخصّصة التي لم تعُد مطلوبة. يمكن أن يؤدي تسرُّب الذاكرة إلى طلب التطبيق مزيدًا من الذاكرة من نظام التشغيل أكثر مما هو متاح، ما يؤدي إلى تعطُّل التطبيق. يمكن أن تؤدي بعض الممارسات غير الصحيحة إلى تسرُّب الذاكرة في تطبيقات Android، مثل عدم التخلص بشكلٍ سليم من الموارد أو عدم إلغاء تسجيل المستمعين عندما لا يعودون مطلوبين.
يوفّر لك هذا المستند بعض أفضل الممارسات للمساعدة في منع تسرُّب الذاكرة في الرمز البرمجي ورصده وحله. إذا جرّبت الطُرق الواردة في هذا المستند وشككت في حدوث تسرُّب للذاكرة في حِزم SDK، يمكنك الاطّلاع على كيفية الإبلاغ عن مشاكل حِزم SDK من Google.
قبل التواصل مع فريق الدعم
قبل الإبلاغ عن تسرُّب ذاكرة إلى فريق دعم Google، اتّبِع أفضل الممارسات بالإضافة إلى خطوات تصحيح الأخطاء الواردة في هذا المستند لمحاولة التأكّد من أنّ الخطأ ليس في الرمز البرمجي. قد تؤدي هذه الخطوات إلى حلّ مشكلتك، وإذا لم تنجح، ستؤدي إلى إنشاء المعلومات التي يحتاج إليها فريق دعم Google ل مساعدتك.
منع تسرّبات الذاكرة
اتّبِع أفضل الممارسات التالية للمساعدة في تجنُّب بعض الأسباب الأكثر شيوعًا ل تسرُّب الذاكرة في الرموز البرمجية التي تستخدِم حِزم تطوير البرامج (SDK) من Google.
أفضل الممارسات المتعلّقة بتطبيقات Android
تأكَّد من تنفيذ كل ما يلي في تطبيق Android:
- إلغاء حجز الموارد غير المستخدَمة
- إلغاء تسجيل المستمعين عند عدم الحاجة إليهم
- إلغاء المهام عندما لا تكون مطلوبة
- توجيه طرق دورة الحياة لإلغاء حجز الموارد
- استخدام أحدث إصدارات حِزم SDK
لمعرفة تفاصيل محدّدة حول كلّ من هذه الممارسات، يُرجى الاطّلاع على الأقسام التالية.
إلغاء حجز الموارد غير المستخدَمة
عندما يستخدم تطبيق Android أحد الموارد، احرص على تحريره عندما لم يعُد مطلوبًا. وفي حال عدم إجراء ذلك، سيستمرّ المورد في استخدام الذاكرة حتى بعد انتهاء تطبيقك من استخدامه. لمزيد من المعلومات، راجِع دورة حياة النشاط في مستندات Android.
إزالة مراجع GoogleMap القديمة في حِزم GeoSDK
من الأخطاء الشائعة أنّ GoogleMap يمكن أن يتسبب في تسرُّب الذاكرة إذا تم تخزينه مؤقتًا باستخدام NavigationView أو MapView. ترتبط GoogleMap بعلاقة 1 إلى 1 مع 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
مباشرةً،
على التوالي. تعالج أجزاء الدعم إعادة توجيه methods lifecycle.
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)
يتم تحديث حِزم تطوير البرامج من Google باستمرار لإضافة ميزات جديدة وإصلاح الأخطاء و إجراء تحسينات على الأداء. يجب تحديث حِزم SDK في تطبيقك لتلقّي هذه الإصلاحات.
تصحيح أخطاء تسرّب الذاكرة
إذا استمر ظهور تسرُّب للذاكرة بعد تنفيذ جميع الاقتراحات السارية المذكورة في هذا المستند سابقًا، اتّبِع هذه العملية لتصحيح الأخطاء.
قبل البدء، يجب أن تكون على دراية بكيفية إدارة Android لملفه الشخصي الذاكرة. للحصول على معلومات، يُرجى قراءة مقالة Android نظرة عامة على إدارة الذاكرة.
لتصحيح أخطاء تسرب الذاكرة، اتّبِع هذه العملية:
- أعِد إظهار المشكلة. هذه الخطوة ضرورية لتصحيح الأخطاء.
- تحقّق مما إذا كان استخدام الذاكرة متوقّعًا. تأكَّد من أنّ الزيادة في الاستخدام التي تبدو وكأنها تسرُّب للذاكرة ليست في الواقع الذاكرة المطلوبة لتشغيل تطبيقك.
- تصحيح الأخطاء على مستوى عالٍ هناك العديد من الأدوات التي يمكنك استخدامها لتصحيح الأخطاء. تساعد ثلاث مجموعات أدوات عادية مختلفة في تصحيح أخطاء الذاكرة في Android: "استوديو Android" وPerfetto وأدوات سطر الأوامر لـ Android Debug Bridge (adb).
- التحقّق من استخدام تطبيقك للذاكرة: احصل على ملف "تجميع الذاكرة" وtracking allocation ثم تحليله.
- إصلاح تسرب الذاكرة:
تتناول الأقسام التالية هذه الخطوات بالتفصيل.
الخطوة 1: إعادة إنشاء المشكلة
إذا لم تتمكّن من إعادة إنشاء المشكلة، ننصحك أولاً بالتفكير في السيناريوهات التي قد تؤدي إلى تسرُّب الذاكرة. قد يكون من المفيد الانتقال مباشرةً إلى الاطّلاع على ملف ملف تفريغ ذاكرة heap dump، إذا كنت تعلم أنّه تم إعادة إنشاء المشكلة. ومع ذلك، إذا حصلت للتو على ملف "تجميع الذاكرة العشوائية" عند بدء تشغيل التطبيق أو في وقت عشوائي آخر، قد لا تكون قد فعّلت الشروط اللازمة لبدء تسرُّب الذاكرة. ننصحك بالعمل على سيناريوهات مختلفة عند محاولة إعادة ظهور المشكلة:
ما هي مجموعة الميزات التي تم تفعيلها؟
ما هي التسلسلات المحدّدة لإجراءات المستخدمين التي تؤدي إلى حدوث تسرُّب البيانات؟
- هل حاولت تكرار عمليات تفعيل هذه التسلسلات؟
ما هي حالات دورة الحياة التي مرّ بها التطبيق؟
- هل جرّبت عدّة تكرارات خلال مراحل دورة الحياة المختلفة؟
تأكَّد من أنّه يمكنك إعادة إنشاء المشكلة في أحدث إصدار من حِزم SDK. قد يكون قد تم حلّ المشكلة في إصدار سابق.
الخطوة 2: التحقّق مما إذا كان استخدام الذاكرة للتطبيق متوقّعًا
تتطلّب كل ميزة ذاكرة إضافية. عند تصحيح أخطاء السيناريوهات المختلفة، عليك التفكير في ما إذا كان هذا الاستخدام متوقّعًا أم لا أو ما إذا كان هناك تسرُّب للذاكرة. على سبيل المثال، بالنسبة إلى الميزات أو مهام المستخدمين المختلفة، ننصحك بالتفكير في الاحتمالات التالية:
تسرُّب محتمل: يؤدي تفعيل السيناريو من خلال عمليات تكرار متعددة إلى زيادة في استخدام الذاكرة بمرور الوقت.
الاستخدام المتوقّع على الأرجح للذاكرة: تتم استعادة الذاكرة بعد إيقاف السيناريو.
الاستخدام المتوقّع للذاكرة: يزداد استخدام الذاكرة لفترة من الوقت ثم ينخفض تدريجيًا. قد يرجع ذلك إلى ذاكرة تخزين مؤقت محدودة أو استخدام ذاكرة آخر متوقّع.
إذا كان من المرجّح أن يكون سلوك التطبيق هو استخدام الذاكرة المتوقّع، يمكن حلّ المشكلة من خلال إدارة ذاكرة تطبيقك. للحصول على المساعدة، يُرجى الاطّلاع على مقالة إدارة ذاكرة تطبيقك.
الخطوة 3: تصحيح الأخطاء على مستوى عالٍ
عند تصحيح أخطاء تسرب الذاكرة، ابدأ من مستوى عالٍ، ثم تعمَّق في التفاصيل بعد تضييق نطاق الاحتمالات. استخدِم إحدى أدوات debugging الرفيعة المستوى هذه لتحليل ما إذا كان هناك تسرّب للموارد بمرور الوقت:
أداة تحليل الذاكرة في "استوديو Android" (إجراء مقترَح)
أداة تحليل الذاكرة في Android Studio
تمنحك هذه الأداة مخطّطًا بيانيًا مركّبًا للذاكرة المستخدَمة. يمكن أيضًا بدء عمليات تفريغ الذاكرة المؤقتة وتتبُّع التخصيص من هذه الواجهة نفسها. هذه الأدوات هي الاقتراحات التلقائية. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة أداة تحليل الذاكرة في "استوديو Android".
عدادات الذاكرة في Perfetto
يمنحك Perfetto إمكانية التحكّم بدقة في تتبُّع عدّة مقاييس وعرضها كلها في مخطّط بياني تكراري واحد. لمزيد من المعلومات، يُرجى الاطّلاع على عدادات ذاكرة Perfetto.
أدوات سطر الأوامر في Android Debug Bridge (adb)
إنّ الكثير من المعلومات التي يمكنك تتبُّعها باستخدام Perfetto متوفّرة أيضًا كadb
أداة سطر أوامر يمكنك الاستعلام عنها مباشرةً. في ما يلي مثالان مهمان:
يتيح لك Meminfoاطلاعًا على معلومات مفصّلة عن الذاكرة في وقت معيّن.
يوفّر Procstats بعض الإحصاءات المجمّعة المهمة بمرور الوقت.
من الإحصاءات المهمة التي يجب الاطّلاع عليها هنا هي الحد الأقصى للمساحة التي يشغلها التطبيق في الذاكرة الفعلية
(maxRSS) بمرور الوقت. قد لا تكون دقة MaxPSS عالية. للاطّلاع على
طريقة لزيادة الدقة، راجِع علامة
adb shell dumpsys procstats --help –start-testing
.
تتبُّع التخصيص
يحدِّد تتبُّع التخصيص تسلسل استدعاء الدوال البرمجية الذي تم فيه تخصيص الذاكرة ويحدد ما إذا تم تحريرها. وتُعدّ هذه الخطوة مفيدة بشكل خاص عند تتبُّع عمليات تسرُّب ملف برمجي في الرمز البرمجي الأصلي. بما أنّ هذه الأداة تحدد تسلسل استدعاء الدوال البرمجية، يمكن أن تكون وسيلة رائعة لإصلاح السبب الأساسي للخطأ بسرعة أو معرفة كيفية إعادة إنشاء المشكلة. لمعرفة خطوات استخدام ميزة تتبُّع عمليات التوزيع، يُرجى الاطّلاع على مقالة تصحيح أخطاء الذاكرة في الرموز البرمجية الأصلية باستخدام ميزة تتبُّع عمليات التوزيع.
الخطوة 4: التحقّق من استخدام تطبيقك للذاكرة باستخدام أداة تفريغ الذاكرة
تتمثل إحدى طرق رصد تسرُّب الذاكرة في الحصول على مخطّط تجميع للذاكرة لتطبيقك ثم فحصه بحثًا عن أي تسرُّبات. تجميع الذاكرة هو لقطة لجميع العناصر في ذاكرة التطبيق. ويمكن استخدامه لتشخيص تسرب الذاكرة وغيرها من المشاكل المتعلّقة بالذاكرة.
يمكن لخدمة Android Studio رصد عمليات تسرُّب الذاكرة التي لا يمكن لنظام جمع القمامة إصلاحها. عند تسجيل ملف "تجميع الذاكرة"، يتحقّق Android Studio ممّا إذا كان هناك نشاط أو جزء لا يزال بالإمكان الوصول إليه ولكن سبق أن تم إزالته.
- تسجيل نَسخة من الذاكرة
- تحليل ملف "تجميع الذاكرة" للعثور على عمليات تسرُّب الذاكرة
- إصلاح تسرب الذاكرة:
لمعرفة التفاصيل، يُرجى الاطّلاع على الأقسام التالية.
تسجيل نَسْخ الذاكرة
لتسجيل نَسخة ذاكرة، يمكنك استخدام أداة 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".
انقر على تشغيل، ثم على إعدادات تصحيح الأخطاء.
افتح علامة التبويب أداة تحليل أداء Android.
اختَر الذاكرة.
اختَر فتح ملف "تجميع الذاكرة" واختَر ملف "تجميع الذاكرة" الذي أنشأته. يعرض أداة تحليل الذاكرة رسمًا بيانيًا لاستخدام تطبيقك للذاكرة.
استخدِم الرسم البياني لتحليل ملف "تجميع الذاكرة العشوائية":
تحديد العناصر التي لم تعُد مستخدَمة
تحديد العناصر التي تستهلك الكثير من الذاكرة
الاطّلاع على مقدار الذاكرة التي يستخدمها كل عنصر
استخدِم هذه المعلومات لتضييق نطاق مصدر تسرّب الذاكرة أو العثور عليه وإصلاحه.
الخطوة 5: إصلاح تسرب الذاكرة
بعد تحديد مصدر تسرُّب الذاكرة، يمكنك إصلاحه. يساعد حلّ مشاكل تسرب الذاكرة في تطبيقات Android على تحسين أداء التطبيقات واستقرارها. تختلف التفاصيل حسب السيناريو. ومع ذلك، يمكن أن تساعدك الاقتراحات التالية:
تأكَّد من أنّ تطبيقك يخصّص الذاكرة ويُلغي تخصيصها على النحو المُقترَح فيموضوع Android بعنوان إدارة ذاكرة تطبيقك.
أزِل الرموز أو الموارد غير المستخدَمة من تطبيقك. للاطّلاع على تفاصيل عن تطبيقات Android، يُرجى الاطّلاع على أفضل الممارسات المتعلّقة بتطبيقات Android.
أدوات تصحيح الأخطاء الأخرى
بعد إكمال هذه الخطوات، إذا لم يتم العثور على ملف برمجي يتسبب في استهلاك زايد للذاكرة وإصلاحه، جرِّب هذه الأدوات:
- تصحيح أخطاء الذاكرة في الرمز الأصلي باستخدام ميزة تتبُّع التخصيص
- تحديد عمليات تسرُّب البيانات باستخدام LeakCanary
تصحيح أخطاء الذاكرة في الرمز الأصلي من خلال تتبُّع عمليات التخصيص
حتى إذا لم تكن تستخدِم رمزًا أصليًا مباشرةً، فإنّ العديد من مكتبات Android الشائعة تستخدِمه، بما في ذلك حِزم SDK من Google. إذا كنت تعتقد أنّ تسرُّب الذاكرة يحدث في الرمز البرمجي الأصلي، تتوفر عدة أدوات يمكنك استخدامها لتصحيح أخطاء هذا الرمز. إنّ تتبُّع عمليات التخصيص باستخدام Android Studio أو heapprofd (متوافق أيضًا مع Perfetto) هو طريقة رائعة لتحديد الأسباب المحتمَلة ل تسرُّب الذاكرة، وغالبًا ما يكون أسرع طريقة لتصحيح الأخطاء.
توفّر ميزة تتبُّع التخصيص أيضًا ميزة مميّزة تتيح لك مشاركة النتائج بدون تضمين معلومات حسّاسة يمكن العثور عليها في ذاكرة عشوائية.
تحديد عمليات تسرُّب البيانات باستخدام LeakCanary
LeakCanary هي أداة فعّالة لتحديد عمليات تسرُّب الذاكرة في تطبيقات Android. للتعرّف على مزيد من المعلومات عن كيفية استخدام LeakCanary في تطبيقك، يُرجى الانتقال إلى LeakCanary.
كيفية الإبلاغ عن مشاكل في حِزم تطوير البرامج (SDK) من Google
إذا جرّبت الطرق الواردة في هذا المستند وتشكّكت في حدوث تسرّب للذاكرة في حِزم تطوير البرامج (SDK) الخاصة بنا، يُرجى التواصل مع فريق دعم العملاء مع تضمين أكبر قدر ممكن من المعلومات التالية:
خطوات إعادة إنشاء تسرب الذاكرة إذا كانت الخطوات تتطلّب ترميزًا معقّدًا، قد يساعدك نسخ الرمز الذي يكرّر المشكلة في نموذج التطبيق وتقديم خطوات إضافية يجب اتّخاذها في واجهة المستخدم لبدء تسرّب البيانات.
عمليات تفريغ الذاكرة المحفوظة من تطبيقك الذي تم إعادة إنشاء المشكلة فيه سجِّل ملفّات تفريغ heap في نقطتَين زمنيتَين مختلفتَين توضِّح أنّ استخدام الذاكرة زاد بمقدار كبير.
إذا كان من المتوقّع حدوث تسرُّب للذاكرة الأصلية، شارِك ناتج تتبُّع عمليات التخصيص من heapprofd.
تقرير خطأ تم إنشاؤه بعد إعادة إنشاء حالة تسرُّب البيانات
تتبُّع تسلسل استدعاء الدوال البرمجية لأي أعطال متعلقة بالذاكرة
ملاحظة مهمة: لا تكفي عادةً عمليات تتبُّع تسلسل استدعاء الدوال البرمجية وحدها لتحديد وحلّ المشاكل المتعلّقة بالذاكرة، لذا احرص أيضًا على تقديم أحد أشكال المعلومات الأخرى.