אפשר לצלם תמונת מצב של הזיכרון כדי לראות אילו אובייקטים באפליקציה תופסים זיכרון בזמן הצילום, ולזהות דליפות זיכרון או התנהגות של הקצאת זיכרון שמובילה לגמגום, לקפיאות ואפילו לקריסות של האפליקציה. מומלץ במיוחד ליצור עותקים של ה-heap אחרי הפעלת המשתמש למשך זמן ממושך, כי יכול להיות שיוצגו אובייקטים שעדיין נמצאים בזיכרון אבל לא אמורים להיות שם יותר.
בדף הזה מתואר כלי ש-Android Studio מספק לאיסוף ולניתוח של נתוני Heap Dump. לחלופין, אפשר לבדוק את הזיכרון של האפליקציה משורת הפקודה באמצעות dumpsys וגם לראות אירועים של איסוף אשפה (GC) ב-Logcat.
למה כדאי ליצור פרופיל של הזיכרון של האפליקציה
Android מספק סביבת זיכרון מנוהלת – כש-Android קובע שהאפליקציה שלכם כבר לא משתמשת בחלק מהאובייקטים, איסוף האשפה משחרר את הזיכרון שלא בשימוש בחזרה ל-heap. השיטה שבה מערכת Android מוצאת זיכרון לא בשימוש משתפרת כל הזמן, אבל בשלב מסוים בכל הגרסאות של Android, המערכת חייבת להשהות את הקוד שלכם לזמן קצר. ברוב המקרים, ההשהיות לא מורגשות. עם זאת, אם האפליקציה מקצה זיכרון מהר יותר מהמהירות שבה המערכת יכולה לאסוף אותו, יכול להיות שיהיה עיכוב באפליקציה בזמן שהמערכת מפנה מספיק זיכרון כדי לענות על ההקצאות. העיכוב עלול לגרום לאפליקציה לדלג על פריימים ולגרום להאטה נראית לעין.
גם אם האפליקציה לא פועלת לאט, אם יש בה דליפת זיכרון, היא יכולה לשמור את הזיכרון הזה גם כשהיא פועלת ברקע. ההתנהגות הזו עלולה להאט את הביצועים של שאר הזיכרון במערכת, כי היא גורמת לאירועים מיותרים של איסוף זבל. בסופו של דבר, המערכת נאלצת להפסיק את תהליך האפליקציה כדי לפנות זיכרון. אחר כך, כשהמשתמש חוזר לאפליקציה, התהליך של האפליקציה צריך להתחיל מחדש לגמרי.
מידע על שיטות תכנות שיכולות להפחית את השימוש בזיכרון של האפליקציה זמין במאמר ניהול הזיכרון של האפליקציה.
סקירה כללית של תמונת מצב של הזיכרון
כדי לצלם תמונת מצב של הזיכרון, בוחרים במשימה Analyze Memory Usage (Heap Dump) (משתמשים ב-Profiler: run 'app' as debuggable (complete data)) כדי לצלם תמונת מצב של הזיכרון. במהלך יצירת ה-dump של ה-heap, כמות הזיכרון של Java עשויה לגדול באופן זמני. זה מצב תקין כי תמונת המצב של הזיכרון נוצרת באותו תהליך כמו האפליקציה, ונדרש זיכרון כדי לאסוף את הנתונים. אחרי שמבצעים צילום של ה-heap dump, מוצגות האפשרויות הבאות:
ברשימת הכיתות מוצגים הפרטים הבאים:
- הקצאות: מספר ההקצאות בערימה.
גודל מקורי: הכמות הכוללת של הזיכרון המקורי שנעשה בו שימוש על ידי סוג האובייקט הזה (בבייט). במקרים מסוימים, תראו כאן את הזיכרון שהוקצה לאובייקטים ב-Java, כי מערכת Android משתמשת בזיכרון מקומי עבור חלק ממחלקות ה-framework, כמו
Bitmap.גודל שטחי: כמות הזיכרון הכוללת ב-Java שנעשה בה שימוש על ידי סוג האובייקט הזה (בבייטים).
הנפח שמתפנה: הגודל הכולל של הזיכרון שנשמר בגלל כל המופעים של המחלקה הזו (בבייטים).
משתמשים בתפריט הערימה כדי לסנן ערימות מסוימות:
- זיכרון Heap של האפליקציה (ברירת מחדל): הזיכרון הראשי שבו האפליקציה מקצה זיכרון.
- Image heap: קובץ האימג' לאתחול המערכת, שמכיל מחלקות שנטענות מראש במהלך האתחול. הקצאות שמוגדרות כאן לא משתנות ולא נעלמות.
- Zygote heap: ה-heap של העתקה בעת כתיבה, שממנו מתבצע פיצול של תהליך האפליקציה במערכת Android.
משתמשים בתפריט הנפתח 'סידור' כדי לבחור איך לסדר את הקצאות המשאבים:
- סידור לפי כיתה (ברירת מחדל): כל ההקצאות מקובצות לפי שם הכיתה.
- סידור לפי חבילה: כל ההקצאות מקובצות לפי שם החבילה.
משתמשים בתפריט הנפתח של הכיתות כדי לסנן קבוצות של כיתות:
- כל השיעורים (ברירת מחדל): מוצגים כל השיעורים, כולל אלה מהספריות ומהתלויות.
- הצגת דליפות של פעילות או של מקטעי קוד: הצגת מחלקות שגורמות לדליפות זיכרון.
- הצגת כיתות של פרויקט: הצגת כיתות שהוגדרו רק על ידי הפרויקט.
לוחצים על שם של מחלקה כדי לפתוח את החלונית Instance (מופע). כל מופע שמופיע ברשימה כולל את הפרטים הבאים:
- עומק: מספר הדילוגים הקצר ביותר מכל שורש GC למופע שנבחר.
- גודל מקורי: הגודל של המופע הזה בזיכרון המקורי. העמודה הזו גלויה רק ב-Android מגרסה 7.0 ואילך.
- גודל שטחי: הגודל של המופע הזה בזיכרון של Java.
- הגודל נשמר: גודל הזיכרון שמופע זה תופס (כפי שמופיע בעץ השליטה).
לוחצים על מופע כדי להציג את פרטי המופע, כולל השדות וההפניות שלו. סוגים נפוצים של שדות והפניות הם סוגים מובנים
,
מערכים
,
וסוגי נתונים פרימיטיביים
ב-Java. לוחצים לחיצה ימנית על שדה או על הפניה כדי לעבור למופע או לשורה המשויכים בקוד המקור.
- שדות: מוצגים כל השדות במופע הזה.
- הפניות: מציג את כל ההפניות לאובייקט שמודגש בכרטיסייה מופע.
איך מוצאים דליפות זיכרון
כדי לסנן במהירות את הכיתות שאולי משויכות לדליפות זיכרון, פותחים את התפריט הנפתח של הכיתה ובוחרים באפשרות הצגת דליפות של פעילות או של מקטעים. Android Studio מציג מחלקות שלדעתו מצביעות על דליפות זיכרון עבור מופעים של Activity ושל Fragment באפליקציה.
כדי לחפש דליפות זיכרון באופן ידני יותר, אפשר לעיין ברשימות של המחלקות והמופעים כדי למצוא אובייקטים עם גודל שמור גדול. מחפשים דליפות זיכרון שנגרמות בגלל אחת מהסיבות הבאות:
- הפניות לטווח ארוך אל
Activityאו אלContextשעלולות לגרום לדליפה של גרף הקומפוזיציה של Compose המתארח (למשלComposeViewוהרכיבים המשניים שלו). - הדלפה של אובייקטים של מצב Jetpack Compose (
MutableState), מאחסני מצב או ביטויי למדה שתופסיםContext. - שוכחים לנקות את המאזינים או את הצופים בבלוק
onDisposeשלDisposableEffect. - מחלקות פנימיות לא סטטיות, כמו
Runnable, שיכולות להכיל מופע שלActivity. - מטמון שמכיל אובייקטים יותר זמן מהנדרש.
כשמזהים דליפות זיכרון פוטנציאליות, אפשר להשתמש בכרטיסיות Fields ו-References ב-Instance Details כדי לעבור למופע או לשורת קוד המקור הרלוונטיים.
הפעלת דליפות זיכרון לצורך בדיקה
כדי לנתח את השימוש בזיכרון, צריך להעמיס על קוד האפליקציה ולנסות לכפות דליפות זיכרון. דרך אחת לגרום לדליפות זיכרון באפליקציה היא להפעיל אותה למשך זמן מסוים לפני שבודקים את ה-heap. יכול להיות שדליפות יגיעו לחלק העליון של ההקצאות ב-heap. עם זאת, ככל שהדליפה קטנה יותר, כך צריך להריץ את האפליקציה יותר זמן כדי לראות אותה.
אפשר גם להפעיל דליפת זיכרון באחת מהדרכים הבאות:
- מסובבים את המכשיר לאורך ולרוחב כמה פעמים בזמן שהוא במצבי פעילות שונים. סיבוב המכשיר יכול לגרום לאפליקציה לדלוף של
Activity(וכתוצאה מכך של עץ ממשק המשתמש של Compose שמתארח בו ועצי המצב המשויכים), אם האפליקציה מחזיקה הפניה ל-Activityאו ל-Contextבתוך פעולות אסינכרוניות או מחזיקי מצב. - לעבור בין האפליקציה שלכם לבין אפליקציה אחרת כשמצבי הפעילות שונים. לדוגמה, עוברים למסך הבית ואז חוזרים לאפליקציה.
ייצוא וייבוא של הקלטת תמונת מצב של הזיכרון
אפשר לייצא ולייבא קובץ של תמונת מצב של הזיכרון מהכרטיסייה הקלטות קודמות בכלי לניתוח ביצועים (profiler). Android Studio שומר את ההקלטה כקובץ .hprof.
לחלופין, כדי להשתמש בכלי אחר לניתוח קבצים מסוג .hprof כמו jhat, צריך להמיר את קובץ .hprof מפורמט Android לפורמט קובץ .hprof של Java SE. כדי להמיר את פורמט הקובץ, משתמשים בכלי hprof-conv שמופיע בספרייה {android_sdk}/platform-tools/. מריצים את הפקודה hprof-conv עם שני ארגומנטים: שם הקובץ המקורי .hprof והמיקום שבו רוצים לכתוב את הקובץ .hprof שהומר, כולל שם הקובץ החדש .hprof. לדוגמה:
hprof-conv heap-original.hprof heap-converted.hprof