Middle+
Πώς να εντοπίσετε την ύπαρξη διαρροής μνήμης κατά την ανάλυση ενός dump;
sobes.tech AI
Απάντηση από AI
Για την ανίχνευση διαρροών μνήμης σε ένα dump (αρχείο HPROF), χρησιμοποιούνται εργαλεία που αναλύουν το γράφημα αντικειμένων στη στοίβα. Βασικά βήματα:
-
Λήψη dump μνήμης:
- Μέσω του Memory Profiler του Android Studio.
- Με την εντολή
adb shell dumpheap <όνομα πακέτου> /data/local/tmp/dump.hprof. - Με την κλήση συστήματος
Debug.dumpHprofData(filePath).
-
Ανάλυση του dump:
- Άνοιγμα του dump στο Android Studio: στον Memory Profiler ή μέσω του μενού "File" -> "Open".
- Ανάλυση αντικειμένων: ταξινόμηση των αντικειμένων κατά μέγεθος (Shallow Size, Retained Size) και αριθμό αντιγράφων.
- Αναζήτηση ύποπτων αντικειμένων: αναζητήστε κλάσεις που πρέπει να καταστραφούν (π.χ., Activity, Fragment, Contexts), αλλά έχουν πολλά αντίγραφα ή μεγάλο
Retained Size. - Μελέτη της διαδρομής προς το αντικείμενο (Reference Chain): επιλέξτε ένα ύποπτο αντικείμενο και παρακολουθήστε το μονοπάτι του προς τα ριζικά αντικείμενα (GC roots). Αυτό θα δείξει ποιος διατηρεί την αναφορά, αποτρέποντας τη συλλογή απορριμμάτων.
- Αναζήτηση στατικών αναφορών: τα στατικά πεδία συχνά αποτελούν πηγή διαρροών, αν αποθηκεύουν μακροχρόνιες αναφορές σε συμφραζόμενα ή προβολές.
- Χρήση LeakCanary: η βιβλιοθήκη αυτοματοποιεί την ανίχνευση, το dump και την ανάλυση διαρροών σε πραγματικό χρόνο, παρέχοντας λεπτομερή περιγραφή της διαδρομής διαρροής.
-
Ερμηνεία αποτελεσμάτων:
- Μια μεγάλη διαδρομή προς το GC root που περιέχει αναφορές σε αντικείμενα που πρέπει να καταστραφούν υποδεικνύει πρόβλημα.
- Αναφορές από στατικά πεδία, AsyncTask, χειριστές με καθυστερήσεις, listeners/callbacks που δεν έχουν αποεγγραφεί σωστά ή singleton σε δραστηριότητες ή προβολές συχνά αποτελούν αιτίες διαρροών.
Παράδειγμα ανάλυσης της διαδρομής προς το GC root στο Android Studio Memory Profiler:
// Παράδειγμα διαδρομής προς GC root που υποδεικνύει διαρροή
// android.app.Activity instance με mDestroyed=true
// αναφορά σε android.widget.LinearLayout
// αναφορά σε android.view.View $ListenerInfo
// αναφορά σε com.example.MyActivity$1 (ανώνυμη κλάση που υλοποιεί View.OnClickListener)
// αναφορά σε com.example.MyActivity (αναφορά που προκαλεί τη διαρροή)
Σε αυτό το παράδειγμα, μια ανώνυμη κλάση (ακούγοντας κλικ κουμπιού) διατηρεί μια έμμεση αναφορά στο MyActivity, παρόλο που η δραστηριότητα θα έπρεπε ήδη να έχει καταστραφεί (mDestroyed=true). Αυτός ο ακροατής φαίνεται να καταγράφεται ή να διατηρείται από ένα άλλο μακροχρόνιο αντικείμενο (π.χ., στατικό πεδίο ή singleton).