2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Le thrashing de la mémoire fait référence à la création et à la destruction d'un grand nombre d'objets sur une courte période de temps, entraînant des activités fréquentes de garbage collection (Garbage Collection, GC). Cette activité fréquente du GC consomme beaucoup de ressources CPU et peut entraîner des retards d'application ou une dégradation des performances.
Performances : la courbe de mémoire est irrégulière.
Une fuite de mémoire se produit lorsqu'une application contient des références à des objets qui ne sont plus nécessaires, ce qui empêche le recyclage de ces objets par le ramasse-miettes, occupant ainsi de l'espace mémoire qui aurait pu être libéré. Au fil du temps, les fuites de mémoire entraînent de moins en moins de mémoire disponible, ce qui peut éventuellement entraîner des pannes d'applications ou une dégradation des performances.
Un dépassement de mémoire se produit lorsqu'une application tente d'allouer plus d'espace mémoire, mais que le système ne parvient pas à satisfaire la demande car il n'y a plus assez d'espace mémoire à allouer. Cela amène généralement l’application à lever une exception OutOfMemoryError.
Structure de la mémoire Java : tas, pile de machines virtuelles, zone de méthodes, compteur de programme, pile de méthodes locale.
Algorithme de recyclage de mémoire Java :
Inconvénients de l'algorithme de marquage-effacement : Le marquage et l'effacement ne sont pas efficaces et produiront un grand nombre de fragments de mémoire discontinus.
Algorithme de réplication : simple à mettre en œuvre et efficace à exécuter. Inconvénients : Gaspillage de la moitié de l’espace.
Algorithme Mark-compact : évitez la fragmentation de la mémoire causée par le nettoyage et évitez de perdre de l'espace avec l'algorithme de copie.
L'allocation élastique de la mémoire Android, la valeur d'allocation et la valeur maximale sont affectées par des appareils spécifiques.
L'algorithme de recyclage Dalvik et l'algorithme de recyclage ART sont tous deux des mécanismes de récupération de place utilisés pour la gestion de la mémoire dans le système d'exploitation Android.
Algorithme de recyclage Dalvik :
Algorithme de recyclage d’art :
Mécanisme 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 peut afficher les allocations de mémoire, cliquez sur « Enregistrer les allocations Java/Kotlin ».
Signification de ce qui précède :
Les significations suivantes :
malloc()
ounew
Le nombre d'objets alloués par l'opérateur.free()
oudelete
Le nombre d'objets désalloués par l'opérateur.Analyse de l'image ci-dessus :
Les valeurs des allocations et des désallocations dans cette zone sont relativement similaires et la taille peu profonde est relativement grande, ce qui indique que les objets peuvent être fréquemment créés et détruits.
Après avoir cliqué, vous pouvez afficher les informations de la pile d'appels et, en combinaison avec le code, vous pouvez en déduire qu'il existe un problème de gigue de mémoire dans le gestionnaire.
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() {
}
}
Ajoutez des bibliothèques dépendantes :
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
Après une fuite de mémoire, LeakCanary générera des informations pertinentes et les videra automatiquement :
Comme le montre la figure ci-dessus : LeakActivity a une fuite de mémoire et la relation de chaîne de référence est affichée.
Bien entendu, vous pouvez également générer un fichier hprof et afficher des informations spécifiques via l'outil Profiler :
Comme le montre l'image ci-dessus : 10 points de fuite se sont produits, y compris LeakActivity. Cliquez sur LeakActivity pour afficher l'objet ayant subi une fuite de mémoire et vérifier la chaîne de référence. On peut voir qu'il est détenu par ArrayList.
Si vous ne libérez pas les ressources image après avoir utilisé Bitmap, il est facile de provoquerFuite de mémoire, entraînant un débordement de mémoire。
Recyclage de la mémoire :
Bitmap.recycle()
Effectuez le recyclage Bitmap.Configuration des pixels bitmap :
Configuration | Taille de l'octet occupé (octet) | illustrer |
---|---|---|
ALPHA_8 | 1 | canal transparent unique |
RVB_565 | 2 | Teinte RVB simple |
ARGB_8888 | 4 | Couleurs vraies 24 bits |
RGBA_F16 | 8 | Android 8.0 Nouveau (HDR) |
Calculez la mémoire occupée par Btimap :
Problème de fichier de ressources :
Code d'essai :
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
*/
illustrer:
1dp sur les appareils mdpi1px, 1dp sur les appareils xhdpi2px, 1dp==3px sur un appareil xxhdpi.
Par conséquent, le périphérique actuel est xxhdpi, donc la largeur de la même image sous la ressource xxhdpi est de 858, sous la ressource mdpi, elle sera agrandie 3 fois et la largeur est de 2574, et sous la ressource xhdpi, elle sera agrandie 1,5 fois et la largeur est de 1287.