תיעוד תמונת מצב של ערימה

אפשר ליצור גרסת dump של אשכול כדי לראות אילו אובייקטים באפליקציה משתמשים בזיכרון בזמן היצירה, ולזהות דליפות זיכרון או התנהגות של הקצאת זיכרון שמובילה לגמגום, לקיפאון ואפילו לקריסות של האפליקציה. כדאי במיוחד תמונת מצב של הזיכרון אחרי סשן ארוך של המשתמש, כשיכול להיות שאובייקטים עדיין מוצגים בזיכרון שכבר לא אמור להופיע.

בדף הזה מתוארים הכלים ש-Android Studio מספקת לאיסוף ולניתוח של דמפים של אשכול. לחלופין, אפשר לבדוק את הזיכרון של האפליקציה משורת הפקודה באמצעות dumpsys וגם לראות אירועי איסוף אשפה (GC) ב-Logcat.

למה כדאי לבצע פרופיל של זיכרון האפליקציה

Android מספק סביבה של זיכרון מנוהל – כשמערכת Android קובעת שהאפליקציה לא משתמשת יותר באובייקטים מסוימים, מנקה האשפה משחרר את הזיכרון שלא מנוצל בחזרה לאוסף. אנחנו כל הזמן משפרים את האופן שבו Android מאתרת זיכרון שלא בשימוש, אבל בשלב מסוים בכל הגרסאות של Android, המערכת חייבת להשהות את הקוד שלכם לזמן קצר. בדרך כלל, לא ניתן להבחין בהשהיות. עם זאת, אם האפליקציה מקצה זיכרון מהר יותר מכפי שהמערכת יכולה לאסוף אותו, ייתכן שהאפליקציה תתעכב בזמן שאספן יפנה מספיק זיכרון את ההקצאות שלכם. העיכוב עלול לגרום לכך שהאפליקציה תדלג על פריימים, וכתוצאה מכך היא תאט באופן ניכר.

גם אם האפליקציה לא מציגה איטיות, אם היא ידלפת זיכרון, היא עשויה לשמור את הזיכרון הזה גם כשהוא ברקע. ההתנהגות הזו עלולה להאט את השאר של ביצועי הזיכרון של המערכת על ידי אילוץ איסוף אשפה מיותר אירועים. בסופו של דבר, המערכת נאלצת להרוג את תהליך האפליקציה כדי לפנות את הזיכרון. לאחר מכן, כשהמשתמש חוזר לאפליקציה, תהליך האפליקציה צריך להתחיל מחדש לגמרי.

מידע על שיטות תכנות שעשויות לצמצם את נפח הזיכרון של האפליקציה להשתמש, כדאי לקרוא את המאמר ניהול הזיכרון של האפליקציה.

סקירה כללית של תמונת מצב של הזיכרון

כדי לצלם תמונת מצב של הזיכרון: בוחרים במשימה ניתוח השימוש בזיכרון (Dump Dump) (משתמשים באפשרות Profiler: מריצים את 'app' כניתנה לניפוי באגים (נתונים מלאים)) כדי לצלם תמונת מצב של הזיכרון לזרום. במהלך ה-dump של ה-heap, יכול להיות שגודל הזיכרון של Java יגדל באופן זמני. זה מצב נורמלי כי תמונת מצב של הזיכרון מתרחשת באותו תהליך נדרש קצת זיכרון כדי לאסוף את הנתונים. אחרי שמצלמים את תמונת מצב של הזיכרון:

ברשימה של הכיתות מוצגים הפרטים הבאים:

  • Allocations: מספר ההקצאות ב-heap.
  • Native Size: נפח הזיכרון המקורי הכולל שבו נעשה שימוש על ידי סוג האובייקט הזה (בבייטים). כאן יופיע זיכרון של חלק מהאובייקטים שהוקצו ב-Java, מערכת Android משתמשת בזיכרון מקורי בחלק ממחלקות ה-framework, כמו Bitmap

  • Shallow Size: סך כל הזיכרון ב-Java שבו נעשה שימוש על ידי סוג האובייקט הזה (בבייטים).

  • גודל נשמר: הגודל הכולל של הזיכרון שנשמר בגלל כל המופעים של המחלקה הזו (בבייטים).

אפשר להשתמש בתפריט ה-heap כדי לסנן לפי אשכולות מסוימים:

  • App heap (ברירת מחדל): אשכול הזיכרון הראשי שאליו האפליקציה מקצה זיכרון.
  • Image heap: קובץ האתחול של המערכת, שמכיל כיתות שנטענו מראש במהלך האתחול. אי אפשר למחוק כאן הקצאות.
  • Zygote heap: אשכול ה-copy-on-write שממנו מתבצעת ההסתעפות של תהליך האפליקציה במערכת Android.

בתפריט הנפתח 'סידור' בוחרים איך לסדר את ההקצאות:

  • סידור לפי כיתה (ברירת המחדל): קיבוץ כל ההקצאות לפי שם הכיתה.
  • סידור לפי חבילה: קיבוץ כל ההקצאות לפי שם החבילה.

אפשר להשתמש בתפריט הנפתח של הכיתות כדי לסנן לקבוצות של כיתות:

  • כל הכיתות (ברירת מחדל): הצגת כל הכיתות, כולל הכיתות מספריות. של יחסי התלות.
  • הצגת דליפות של פעילות/קטעים: הצגת המחלקות שגורמות לדליפות זיכרון.
  • הצגת כיתות הפרויקט: מוצגות רק כיתות שהוגדרו בפרויקט.

לוחצים על שם מחלקה כדי לפתוח את החלונית מכונה. כל מכונה ברשימה כוללת את הפרטים הבאים:

  • עומק: המספר הקצר ביותר של צעדים מהשורש של GC אל השורש שנבחר מכונה.
  • Native size (גודל מקורי): הגודל של המכונה הזו בזיכרון הנייטיב. העמודה הזו גלויה רק במכשירי Android מגרסה 7.0 ואילך.
  • Shallow Size: הגודל של המכונה הזו בזיכרון Java.
  • Retained Size: גודל הזיכרון שבו המופע הזה שולט (לפי עץ הדומיננטים).

לוחצים על מכונה כדי להציג את פרטי המכונה, כולל השדות וההפניות שלה. סוגי שדות וקובצי עזר נפוצים הם סוגי נתונים מובְנים , מערכי נתונים וסוגי נתונים פרימיטיביים ב-Java. לוחצים לחיצה ימנית על שדה או על הפניה כדי לעבור למופע המשויך, או בקוד המקור.

  • שדות: הצגת כל השדות במופע הזה.
  • References: הצגת כל הפניה לאובייקט שמודגש Instance.

איתור דליפות זיכרון

כדי לסנן במהירות לכיתות שעשויות להיות קשורות לדליפות זיכרון, פותחים את התפריט הנפתח של הכיתות ובוחרים באפשרות Show activity/fragment leaks. ב-Android Studio מוצגות כיתות שלדעת המערכת מצביעות על דליפות זיכרון במכונות Activity ו-Fragment באפליקציה. סוגי הנתונים שמוצגים במסנן כוללים את הנתונים הבאים:

  • מכונות Activity שהושמדו אבל עדיין יש להן הפניות.
  • Fragment מופעים ללא ערך תקין FragmentManager אבל הם עדיין שהוזכרו.

שימו לב שהמסנן עלול להניב תוצאות חיוביות מוטעות במקרים הבאים מצבים:

  • נוצר Fragment אבל עדיין לא נעשה בו שימוש.
  • ה-Fragment נשמר במטמון, אבל לא כחלק מ-FragmentTransaction.

כדי לחפש דליפות זיכרון באופן ידני יותר, אפשר לעיין ברשימות המחלקות והמכונות כדי למצוא אובייקטים בעלי גודל נשמר גדול. חיפוש דליפות זיכרון שנגרמות על ידי הבאים:

  • הפניות לטווח ארוך ל-Activity,‏ Context,‏ View,‏ Drawable ואובייקטים אחרים שעשויים להכיל הפניה למאגר Activity או Context.
  • כיתות פנימיות לא סטטיות, כמו Runnable, שיכול להכיל Activity מכונה.
  • מטמון שמכיל אובייקטים למשך זמן ארוך מהנדרש.

אם מאתרים דליפות זיכרון פוטנציאליות, צריך להשתמש בכרטיסיות שדות והפניות בקטע Instance Details (פרטי המכונה), כדי לדלג לשורה הרלוונטית של קוד המקור או המכונה.

הפעלה של דליפות זיכרון לצורך בדיקה

כדי לנתח את השימוש בזיכרון, צריך להפעיל לחץ על קוד האפליקציה ולנסות לאלץ דליפות זיכרון. אחת הדרכים לעורר דליפות זיכרון באפליקציה היא לתת לה לפעול לזמן מה לפני שבודקים את הערימה. דליפות עשויות להגיע לחלק העליון של מיקום ההקצאות בערימה. עם זאת, ככל שהדליפה קטנה יותר, כך צריך להריץ את האפליקציה למשך זמן ארוך יותר כדי לראות אותה.

אפשר גם לגרום לדליפת זיכרון באחת מהדרכים הבאות:

  • מסובבים את המכשיר מפריסה לאורך לפריסה לרוחב וחוזרים כמה פעמים במצבי פעילות שונים. כיוון המכשיר יכול לגרום לאפליקציה לדלוף אובייקט Activity, Context או View, כי המערכת יוצרת מחדש את Activity. אם האפליקציה שומרת הפניה לאחד מהאובייקטים האלה במקום אחר, המערכת לא יכולה לאסוף את האובייקט הזה.
  • לעבור בין האפליקציה שלכם לאפליקציה אחרת במצבי פעילות שונים. לדוגמה, מנווטים למסך הבית ואז חוזרים לאפליקציה.

ייצוא וייבוא של הקלטה של גרסת dump של אשכול

אפשר לייצא ולייבא קובץ גרסת ביטול של אשכול (heap dump) מהכרטיסייה Past Recordings (הקלטות קודמות) בפרופילר. Android Studio שומר את ההקלטה כקובץ .hprof.

לחלופין, להשתמש בכלי אחר לניתוח קבצים של .hprof, כמו jhat, עליך להמיר את הקובץ .hprof מפורמט Android ל-Java SE פורמט הקובץ .hprof. כדי להמיר את פורמט הקובץ, משתמשים בכלי hprof-conv שמסופק בספרייה {android_sdk}/platform-tools/. הפעלה של hprof-conv פקודה עם שני ארגומנטים: שם הקובץ המקורי .hprof והמיקום לכתוב את קובץ .hprof שהומר, כולל שם הקובץ החדש .hprof. לדוגמה:

hprof-conv heap-original.hprof heap-converted.hprof