le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Il memory thrashing si riferisce alla creazione e distruzione di un gran numero di oggetti in un breve periodo di tempo, con conseguenti frequenti attività di garbage collection (Garbage Collection, GC). Questa frequente attività del GC occupa molte risorse della CPU e può causare ritardi nell'applicazione o un degrado delle prestazioni.
Prestazioni: la curva della memoria è frastagliata.
Una perdita di memoria si verifica quando un'applicazione conserva riferimenti a oggetti che non sono più necessari, impedendo a questi oggetti di essere riciclati dal Garbage Collector, occupando così spazio di memoria che avrebbe potuto essere rilasciato. Con il passare del tempo, le perdite di memoria determinano una quantità sempre minore di memoria disponibile, il che può eventualmente portare a arresti anomali dell'applicazione o al degrado delle prestazioni.
L'overflow della memoria si verifica quando un'applicazione tenta di allocare più spazio di memoria, ma il sistema non è in grado di soddisfare la richiesta perché non c'è più spazio di memoria sufficiente da allocare. Questo di solito fa sì che l'applicazione lanci un'eccezione OutOfMemoryError.
Struttura della memoria Java: heap, stack della macchina virtuale, area dei metodi, contatore dei programmi, stack dei metodi locali.
Algoritmo di riciclo della memoria Java:
Svantaggi dell'algoritmo mark-clear: la marcatura e la cancellazione non sono efficienti e produrranno un gran numero di frammenti di memoria discontinui.
Algoritmo di replica: semplice da implementare ed efficiente da eseguire. Svantaggi: metà dello spazio sprecato.
Algoritmo Mark-compact: evita la frammentazione della memoria causata da Mark-Clean ed evita lo spreco di spazio dell'algoritmo di copia.
L'allocazione elastica della memoria Android, il valore di allocazione e il valore massimo sono influenzati da dispositivi specifici.
L'algoritmo di riciclaggio Dalvik e l'algoritmo di riciclaggio ART sono entrambi meccanismi di garbage collection utilizzati per la gestione della memoria nel sistema operativo Android.
Algoritmo di riciclaggio di Dalvik:
Algoritmo di riciclaggio dell'arte:
Meccanismo 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 può visualizzare le allocazioni di memoria, fare clic su "Registra allocazioni Java/Kotlin".
Significato di quanto sopra:
I seguenti significati:
malloc()
Onew
Il numero di oggetti assegnati dall'operatore.free()
Odelete
Il numero di oggetti deallocati dall'operatore.Analisi dell'immagine sopra:
I valori di allocazioni e deallocazioni in quest'area sono relativamente simili e la dimensione superficiale è relativamente grande, indicando che gli oggetti possono essere creati e distrutti frequentemente.
Dopo aver fatto clic, è possibile visualizzare le informazioni sullo stack di chiamate e, combinate con il codice, è possibile dedurre che esiste un problema di jitter della memoria nel gestore.
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() {
}
}
Aggiungi librerie dipendenti:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
Dopo che si verifica una perdita di memoria, LeakCanary genererà informazioni rilevanti e le scaricherà automaticamente:
Come si può vedere dalla figura sopra: LeakActivity ha una perdita di memoria e viene visualizzata la relazione della catena di riferimenti.
Naturalmente, puoi anche generare un file hprof e visualizzare informazioni specifiche tramite lo strumento Profiler:
Come si può vedere dall'immagine sopra: si sono verificati 10 punti di perdita, incluso LeakActivity. Fare clic su LeakActivity per visualizzare l'oggetto di perdita di memoria e controllare la catena di riferimento. Si può vedere che è mantenuto da ArrayList.
Se non rilasci le risorse dell'immagine dopo aver utilizzato Bitmap, è facile causarloPerdita di memoria, con conseguente overflow della memoria。
Riciclo della memoria:
Bitmap.recycle()
Esegui il riciclo delle bitmap.Configurazione pixel bitmap:
Configurazione | Dimensione byte occupato (byte) | illustrare |
---|---|---|
ALPHA_8 | 1 | unico canale trasparente |
RGB_565 | 2 | Tinta RGB semplice |
ARGB_8888 | 4 | Colore reale a 24 bit |
RGBA_F16 | 8 | Android 8.0 Nuovo (HDR) |
Calcola la memoria occupata da Btimap:
Problema relativo al file di risorse:
Codice di prova:
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
*/
illustrare:
1dp sui dispositivi MDPI1px, 1dp su dispositivi xhdpi2px, 1dp==3px sul dispositivo xxhdpi.
Pertanto, il dispositivo corrente è xxhdpi, quindi la larghezza della stessa immagine sotto la risorsa xxhdpi è 858, sotto la risorsa mdpi verrà ingrandita 3 volte e la larghezza è 2574, e sotto la risorsa xhdpi verrà ingrandita 1,5 volte e la larghezza è 1287.