Mi información de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
La destrucción de memoria se refiere a la creación y destrucción de una gran cantidad de objetos en un corto período de tiempo, lo que resulta en actividades frecuentes de recolección de basura (Garbage Collection, GC). Esta actividad frecuente de GC consume muchos recursos de la CPU y puede provocar retrasos en las aplicaciones o degradación del rendimiento.
Rendimiento: la curva de memoria es irregular.
Se produce una pérdida de memoria cuando una aplicación contiene referencias a objetos que ya no son necesarios, lo que hace que el recolector de basura no pueda recuperar estos objetos, ocupando así espacio de memoria que podría haberse liberado. Con el tiempo, las pérdidas de memoria dan como resultado cada vez menos memoria disponible, lo que eventualmente puede provocar fallas en las aplicaciones o degradación del rendimiento.
El desbordamiento de memoria ocurre cuando una aplicación intenta asignar más espacio de memoria, pero el sistema no puede satisfacer la solicitud porque ya no hay suficiente espacio de memoria para asignar. Esto normalmente hace que la aplicación genere una excepción OutOfMemoryError.
Estructura de la memoria Java: montón, pila de máquina virtual, área de método, contador de programa, pila de método local.
Algoritmo de reciclaje de memoria Java:
Desventajas del algoritmo de marcar y borrar: marcar y borrar no son eficientes y producirán una gran cantidad de fragmentos de memoria discontinuos.
Algoritmo de replicación: simple de implementar y eficiente de ejecutar. Desventajas: Se desperdicia la mitad del espacio.
Algoritmo de marca compacta: evita la fragmentación de la memoria causada por la limpieza de marca y evita desperdiciar espacio del algoritmo de copia.
La asignación elástica de memoria de Android, el valor de asignación y el valor máximo se ven afectados por dispositivos específicos.
El algoritmo de reciclaje Dalvik y el algoritmo de reciclaje ART son mecanismos de recolección de basura utilizados para la administración de memoria en el sistema operativo Android.
Algoritmo de reciclaje de Dalvik:
Algoritmo de reciclaje de arte:
Mecanismo 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 puede ver las asignaciones de memoria, haga clic en "Registrar asignaciones de Java/Kotlin".
Significado de lo anterior:
Los siguientes significados:
malloc()
onew
El número de objetos asignados por el operador.free()
odelete
El número de objetos desasignados por el operador.Análisis de la imagen de arriba:
Los valores de asignaciones y desasignaciones en esta área son relativamente similares y el tamaño superficial es relativamente grande, lo que indica que los objetos se pueden crear y destruir con frecuencia.
Después de hacer clic, puede ver la información de la pila de llamadas y, combinada con el código, puede inferir que hay un problema de fluctuación de la memoria en el Controlador.
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() {
}
}
Agregar bibliotecas dependientes:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
Después de que ocurre una pérdida de memoria, LeakCanary generará información relevante y la volcará automáticamente:
Como se puede ver en la figura anterior: LeakActivity tiene una pérdida de memoria y se muestra la relación de la cadena de referencia.
Por supuesto, también puede generar un archivo hprof y ver información específica a través de la herramienta Profiler:
Como se puede ver en la imagen de arriba: se han producido 10 puntos de fuga, incluido LeakActivity. Haga clic en LeakActivity para ver el objeto con pérdida de memoria y verifique la cadena de referencia.
Si no libera los recursos de la imagen después de usar Bitmap, es fácil causarPérdida de memoria, lo que provoca un desbordamiento de memoria。
Reciclaje de memoria:
Bitmap.recycle()
Realizar reciclaje de mapas de bits.Configuración de píxeles de mapa de bits:
Configuración | Tamaño de bytes ocupados (byte) | ilustrar |
---|---|---|
Alfa_8 | 1 | único canal transparente |
RGB_565 | 2 | Tinte RGB simple |
ARGB_8888 | 4 | Color verdadero de 24 bits |
RGBA_F16 | 8 | Android 8.0 Nuevo (HDR) |
Calcule la memoria ocupada por Btimap:
Problema con el archivo de recursos:
Código de prueba:
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
*/
ilustrar:
1dp en dispositivos mdpi1px, 1dp en dispositivos xhdpi2px, 1dp==3px en dispositivo xxhdpi.
Por lo tanto, el dispositivo actual es xxhdpi, por lo que el ancho de la misma imagen bajo el recurso xxhdpi es 858, bajo el recurso mdpi se ampliará 3 veces y el ancho es 2574, y bajo el recurso xhdpi se ampliará 1,5 veces y el ancho es 1287.