τα στοιχεία επικοινωνίας μου
Ταχυδρομείο[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Το Memory thrashing αναφέρεται στη δημιουργία και καταστροφή μεγάλου αριθμού αντικειμένων σε σύντομο χρονικό διάστημα, με αποτέλεσμα συχνές δραστηριότητες συλλογής σκουπιδιών (Garbage Collection, GC). Αυτή η συχνή δραστηριότητα GC καταλαμβάνει πολλούς πόρους της CPU και μπορεί να προκαλέσει καθυστερήσεις στην εφαρμογή ή υποβάθμιση της απόδοσης.
Απόδοση: Η καμπύλη μνήμης είναι οδοντωτή.
Μια διαρροή μνήμης εμφανίζεται όταν μια εφαρμογή κρατά αναφορές σε αντικείμενα που δεν χρειάζονται πλέον, με αποτέλεσμα να αποτύχει η ανάκτηση αυτών των αντικειμένων από τον συλλέκτη σκουπιδιών, καταλαμβάνοντας έτσι χώρο στη μνήμη που θα μπορούσε να είχε ελευθερωθεί. Με την πάροδο του χρόνου, οι διαρροές μνήμης έχουν ως αποτέλεσμα ολοένα και λιγότερη διαθέσιμη μνήμη, η οποία μπορεί τελικά να οδηγήσει σε σφάλματα εφαρμογής ή υποβάθμιση της απόδοσης.
Η υπερχείλιση μνήμης συμβαίνει όταν μια εφαρμογή επιχειρεί να εκχωρήσει περισσότερο χώρο στη μνήμη, αλλά το σύστημα δεν μπορεί να ικανοποιήσει το αίτημα επειδή δεν υπάρχει πλέον αρκετός χώρος μνήμης για εκχώρηση. Αυτό συνήθως προκαλεί την εφαρμογή να δημιουργήσει μια εξαίρεση OutOfMemoryError.
Δομή μνήμης Java: σωρό, στοίβα εικονικής μηχανής, περιοχή μεθόδων, μετρητής προγράμματος, στοίβα τοπικής μεθόδου.
Αλγόριθμος ανακύκλωσης μνήμης Java:
Μειονεκτήματα του αλγορίθμου σαφής ένδειξης: Η σήμανση και η διαγραφή δεν είναι αποτελεσματικές και θα δημιουργήσουν μεγάλο αριθμό ασυνεχών θραυσμάτων μνήμης.
Αλγόριθμος αναπαραγωγής: απλός στην εφαρμογή και αποτελεσματικός στην εκτέλεση. Μειονεκτήματα: Χάθηκε ο μισός χώρος.
Αλγόριθμος Mark-compact: αποφύγετε τον κατακερματισμό της μνήμης που προκαλείται από το σημάδι καθαρισμού και αποφύγετε τη σπατάλη χώρου στον αλγόριθμο αντιγραφής.
Η ελαστική κατανομή μνήμης Android, η τιμή εκχώρησης και η μέγιστη τιμή επηρεάζονται από συγκεκριμένες συσκευές.
Ο αλγόριθμος ανακύκλωσης Dalvik και ο αλγόριθμος ανακύκλωσης ART είναι μηχανισμοί συλλογής σκουπιδιών που χρησιμοποιούνται για τη διαχείριση μνήμης στο λειτουργικό σύστημα Android.
Αλγόριθμος ανακύκλωσης Dalvik:
Αλγόριθμος ανακύκλωσης τέχνης:
Μηχανισμός LMK:
public class ShakeActivity extends AppCompatActivity {
private static Handler mHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
String str = "";
for (int i = 0; i < 10000000; i++) {
str += i;
}
mHandler.sendEmptyMessageDelayed(1, 30);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shake);
}
public void startClick(View view) {
mHandler.sendEmptyMessage(1);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
Το Memory Profiler μπορεί να δει τις εκχωρήσεις μνήμης, κάντε κλικ στην επιλογή "Εγγραφή εκχωρήσεων Java/Kotlin".
Έννοια των παραπάνω:
Οι ακόλουθες έννοιες:
malloc()
ήnew
Ο αριθμός των αντικειμένων που εκχωρήθηκαν από τον χειριστή.free()
ήdelete
Ο αριθμός των αντικειμένων που εκχωρήθηκαν από τον χειριστή.Ανάλυση της παραπάνω εικόνας:
Οι τιμές των Κατανομών και των Διανομών σε αυτήν την περιοχή είναι σχετικά παρόμοιες και το Ρηχό Μέγεθος είναι σχετικά μεγάλο, υποδεικνύοντας ότι τα αντικείμενα ενδέχεται να δημιουργούνται και να καταστρέφονται συχνά.
Αφού κάνετε κλικ, μπορείτε να προβάλετε τις πληροφορίες της στοίβας κλήσεων και σε συνδυασμό με τον κωδικό, μπορείτε να συμπεράνετε ότι υπάρχει πρόβλημα τρεμούλιασης μνήμης στο Handler.
public class CallbackManager {
public static ArrayList<Callback> sCallbacks = new ArrayList<>();
public static void addCallback(Callback callback) {
sCallbacks.add(callback);
}
public static void removeCallback(Callback callback) {
sCallbacks.remove(callback);
}
}
public class LeakActivity extends AppCompatActivity implements Callback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leak);
ImageView imageView = findViewById(R.id.imageView);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.splash);
imageView.setImageBitmap(bitmap);
CallbackManager.addCallback(this);
}
@Override
public void onOperate() {
}
}
Προσθήκη εξαρτημένων βιβλιοθηκών:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
Μετά την εμφάνιση διαρροής μνήμης, το LeakCanary θα δημιουργήσει σχετικές πληροφορίες και θα τις απορρίψει αυτόματα:
Όπως φαίνεται από το παραπάνω σχήμα: Το LeakActivity έχει διαρροή μνήμης και εμφανίζεται η σχέση της αλυσίδας αναφοράς.
Φυσικά, μπορείτε επίσης να δημιουργήσετε ένα αρχείο hprof και να προβάλετε συγκεκριμένες πληροφορίες μέσω του εργαλείου Profiler:
Όπως φαίνεται από την παραπάνω εικόνα: 10 σημεία διαρροής, συμπεριλαμβανομένου του LeakActivity, κάντε κλικ στο LeakActivity για να δείτε το αντικείμενο που έχει διαρρεύσει και να ελέγξετε την αλυσίδα αναφοράς.
Εάν δεν απελευθερώσετε τους πόρους εικόνας μετά τη χρήση του Bitmap, είναι εύκολο να προκληθείΔιαρροή μνήμης, με αποτέλεσμα υπερχείλιση μνήμης。
Ανακύκλωση μνήμης:
Bitmap.recycle()
Εκτελέστε ανακύκλωση Bitmap.Διαμόρφωση pixel bitmap:
Διαμόρφωση | Μέγεθος κατειλημμένου byte (byte) | εικονογραφώ |
---|---|---|
ALPHA_8 | 1 | ενιαίο διαφανές κανάλι |
RGB_565 | 2 | Απλή απόχρωση RGB |
ARGB_8888 | 4 | 24-bit αληθινό χρώμα |
RGBA_F16 | 8 | Android 8.0 Νέο (HDR) |
Υπολογίστε τη μνήμη που καταλαμβάνει το Btimap:
Πρόβλημα αρχείου πόρων:
Κωδικός δοκιμής:
private void printBitmap(Bitmap bitmap, String drawable) {
String builder = drawable +
" Bitmap占用内存:" +
bitmap.getByteCount() +
" width:" +
bitmap.getWidth() +
" height:" +
bitmap.getHeight() +
" 1像素占用大小:" +
getByteBy1px(bitmap.getConfig());
Log.e("TAG", builder);
}
private int getByteBy1px(Bitmap.Config config) {
if (Bitmap.Config.ALPHA_8.equals(config)) {
return 1;
} else if (Bitmap.Config.RGB_565.equals(config)) {
return 2;
} else if (Bitmap.Config.ARGB_8888.equals(config)) {
return 4;
}
return 1;
}
// 逻辑密度
float density = metrics.density;
// 物理密度
int densityDpi = metrics.densityDpi;
Log.e("TAG", density + "-" + densityDpi);
// 1倍图
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.splash1);
printBitmap(bitmap1, "drawable-mdpi");
// 2倍图
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.splash2);
printBitmap(bitmap2, "drawable-xhdpi");
// 3倍图
Bitmap bitmap3 = BitmapFactory.decodeResource(getResources(), R.drawable.splash3);
printBitmap(bitmap3, "drawable-xxhdpi");
// 4倍图
Bitmap bitmap4 = BitmapFactory.decodeResource(getResources(), R.drawable.splash4);
printBitmap(bitmap4, "drawable-xxxhdpi");
// drawable
Bitmap bitmap5 = BitmapFactory.decodeResource(getResources(), R.drawable.splash);
printBitmap(bitmap5, "drawable");
/*
3.0-480
drawable-mdpi Bitmap占用内存:37127376 width:2574 height:3606 1像素占用大小:4
drawable-xhdpi Bitmap占用内存:9281844 width:1287 height:1803 1像素占用大小:4
drawable-xxhdpi Bitmap占用内存:4125264 width:858 height:1202 1像素占用大小:4
drawable-xxxhdpi Bitmap占用内存:2323552 width:644 height:902 1像素占用大小:4
drawable Bitmap占用内存:37127376 width:2574 height:3606 1像素占用大小:4
*/
εικονογραφώ:
1dp σε συσκευές mdpi1px, 1dp σε συσκευές xhdpi2px, 1dp==3px σε συσκευή xxhdpi.
Επομένως, η τρέχουσα συσκευή είναι xxhdpi, επομένως το πλάτος της ίδιας εικόνας κάτω από τον πόρο xxhdpi είναι 858, κάτω από τον πόρο mdpi θα μεγεθύνεται 3 φορές και το πλάτος είναι 2574, και κάτω από τον πόρο xhdpi θα μεγεθύνεται 1,5 φορές και το πλάτος είναι 1287.