Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

Recomendar la colección, de lo contrario no lo encontramos! ! !

prefacio

En Android, el fenómeno de las pérdidas de memoria son comunes, y una pérdida de memoria como resultado consecuencias hará que la aplicación de golpes En este trabajo una completa introducción a la naturaleza de las pérdidas de memoria, razón y solución, en última instancia, proporcionar alguna herramienta de análisis de pérdida de memoria común, que les guste.

directorio

imagen

1. Introducción

Eso ML (pérdida de memoria) se refiere al fenómeno en la memoria de programa de aplicación, cuando la memoria no tiene que usar, pero no puede ser devuelto al programa lanzado y

2. El impacto de la aplicación

Fácil de hacer que el desbordamiento de memoria de la aplicación, que desbordamiento de la memoria OOM Descripción:

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

3. La naturaleza de la causa de pérdidas de memoria

Descripción específica

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

  • Especial atención desde el punto de vista del mecanismo, porque la presencia de la recolección de basura Java (la GC), una pérdida de memoria no debe existir; se produce pérdida de memoria debido a que sólo las causas holding humano exteriores = involuntariamente referencia de objeto en poder de dicha referencia ciclo de vida> ciclo de vida de referencia

4. base de conocimientos: Android mecanismo de gestión de memoria

4.1 Introducción

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

A continuación, para el proceso de recuperación, la asignación de memoria de objetos, variables y reciclaje a explicar en detalle

4.2 para el proceso de estrategias de memoria . Estrategia de asignación de la memoria A por el ActivityManagerService gestionar de forma centralizada las asignaciones de memoria para todos los procesos b recuperación de la memoria estrategia Paso 1: marco de aplicaciones de tipo proceso de toma Android recuperado en el proceso se aloja, cuando el espacio de proceso es apretado, lo hará. proceso de acuerdo con prioridad baja - proceso de recuperación automática de alto orden >> Android el proceso en cinco niveles de prioridad, de la siguiente manera:

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

Paso 2: Linux kernel marcador específico de recuperación de proceso real ActivityManagerService para todos los procesos (puntuación almacenado en la variable de adj) puntuación para actualizar el kernel Linux kernel de Linux se realiza mediante la recuperación de la memoria real

Resumir aquí sólo los procesos, que complican el proceso, los lectores interesados ​​pueden investigar sistema de código fuente ActivityManagerService.java

4.2 para los objetos, las variables, las estrategias de memoria

  • Android de objetos, variables, estrategias de memoria con Java
  • = Objeto de gestión de memoria de asignación de memoria / variable de desasignación +

A continuación, hablaremos más la asignación de memoria de liberación de memoria y una estrategia. Estrategia de asignación de memoria

  • La memoria de asignación de objetos / responsabilidad automática variable del programa
  • Hay tres clases: distribución estática, dispensación pila, montón y dispensación, respectivamente, para las variables estáticas, variables locales y instancia de objeto se detallan a continuación

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

NOTA: la asignación de memoria utilizada para explicar un ejemplo

public class Sample {    
    int s1 = 0;
    Sample mSample1 = new Sample();   

    // 方法中的局部变量s2、mSample2存放在 栈内存
    // 变量mSample2所指向的对象实例存放在 堆内存
      // 该实例的成员变量s1、mSample1也存放在栈中
    public void method() {        
        int s2 = 0;
        Sample mSample2 = new Sample();
    }
}
    // 变量mSample3所指向的对象实例存放在堆内存
    // 该实例的成员变量s1、mSample1也存放在堆内存中
    Sample mSample3 = new Sample();

b. estrategia de liberación de memoria

  • objetos de liberación de memoria / variables son responsabilidad del recolector de basura de Java (GC) / marco de pila
  • Aquí principalmente en la distribución de destino (es decir, fórmula de asignación de montón) estrategia de liberación de memoria = Java recolector de basura (GC)

Dado que la asignación estática sin liberar la pila a través de un dispensador automático solamente marco de pila, la pila, relativamente simple, y por lo tanto no descrito en detalle

  • recolector de basura de Java (GC) de liberación de memoria = algoritmos de recolección de basura, incluyendo:

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

se detalla a continuación

Optimización del rendimiento de Android: Ali, Tencent y otros conocimientos acerca de las pérdidas de memoria están aquí!

5. Las causas comunes de fugas y soluciones de memoria

conductor común a pérdidas de memoria razones principales:

  1. Colecciones
  2. variables miembro estáticas palabras clave modificada
  3. clases internas / clase anónima no estático
  4. objeto de recurso no está cerrada después de su uso

A continuación, he detallará qué cada pérdidas de memoria gatillo

5.1 colecciones

  • Después de la adición de elementos de memoria, todavía se refieren a divulgar las colecciones razones con un objeto elemento de recogida, haciendo que el objeto es una colección de elementos no pueden ser reciclados, lo que resulta en un ejemplo pérdida de memoria demuestra:
// 通过 循环申请Object 对象 & 将申请的对象逐个放入到集合List
List<Object> objectList = new ArrayList<>();        
       for (int i = 0; i < 10; i++) {
            Object o = new Object();
            objectList.add(o);
            o = null;
        }
// 虽释放了集合元素引用的本身:o=null)
// 但集合List 仍然引用该对象,故垃圾回收器GC 依然不可回收该对象
  • Después de la clase de colección solución para añadir una colección de elementos de los objetos deben ser retirados de la colección después de su uso

Puesto que hay un número de conjunto de elementos, por lo que la forma más fácil de vaciar = & objeto de colección se establece en NULL

 // 释放objectList
        objectList.clear();
        objectList=null;

5.2 variables miembro estáticas modificadas palabras clave

  • reserva de ciclo de vida de los conocimientos que se desea modificar variable miembro estática palabras clave del ciclo de vida de la aplicación =
  • Cuando la razón de fugas Ruoshi citado estático palabra clave modificada instancias de variables miembro de consumo excesivo de los recursos (tales como Context), que es propenso a la vida útil de la variable miembro> ciclo citas vida ejemplo, cuando los casos citados para ser el final del ciclo de vida de la destrucción , que vayan a ejercer una variable estática y no se puede recuperar, por lo que la pérdida de memoria ejemplos para explicar:
public class ClassName {
 // 定义1个静态变量
 private static Context mContext;
 //...
// 引用的是Activity的context
 mContext = context; 

// 当Activity需销毁时,由于mContext = 静态 & 生命周期 = 应用程序的生命周期,故 Activity无法被回收,从而出现内存泄露
}
  • soluciones
  1. Trate de evitar las variables miembro estático citados casos de consumo excesivo de recursos (tales como Context)

Para el contexto de referencia, a continuación, tratar de utilizar el contexto applicaiton

  1. Uso de referencias débiles (WeakReference) mantienen en su posición fuerte ejemplo de referencia

Nota: No es una variable miembro estática ejemplo típico = Singleton

  • singleton conocimiento ya que las características estáticas de reserva, la longitud del ciclo de vida del ciclo de vida de la aplicación =
  • Si existe una fuga objetos razón no es necesario utilizar una sola realización también tiene una referencia de objeto a objeto, el objeto no será recuperado adecuadamente resultando en una pérdida de memoria

Los ejemplos de presentaciones:

// 创建单例时,需传入一个Context
// 若传入的是Activity的Context,此时单例 则持有该Activity的引用
// 由于单例一直持有该Activity的引用(直到整个应用生命周期结束),即使该Activity退出,该Activity的内存也不会被回收
// 特别是一些庞大的Activity,此处非常容易导致OOM

public class SingleInstanceClass {    
    private static SingleInstanceClass instance;    
    private Context mContext;    
    private SingleInstanceClass(Context context) {        
        this.mContext = context; // 传递的是Activity的context
    }  

    public SingleInstanceClass getInstance(Context context) {        
        if (instance == null) {
            instance = new SingleInstanceClass(context);
        }        
        return instance;
    }
}
  • Soluciones simples del ciclo de vida ciclo de vida de la aplicación que se hace referencia de objeto =

En el ejemplo anterior, la aplicación debe transferencia de contexto, porque el ciclo de vida = ciclo de vida de aplicación de la aplicación

public class SingleInstanceClass {    
    private static SingleInstanceClass instance;    
    private Context mContext;    
    private SingleInstanceClass(Context context) {        
        this.mContext = context.getApplicationContext(); // 传递的是Application 的context
    }    

    public SingleInstanceClass getInstance(Context context) {        
        if (instance == null) {
            instance = new SingleInstanceClass(context);
        }        
        return instance;
    }
}

clases internas / clase anónima 5.3 no estáticos

  • Reserva no estático clases internas conocimiento / clase anónima por defecto tiene referencias a la clase externa, y las clases internas estáticas no son
  • Caso común 3 clases, a saber: Los ejemplos de no estático interior class = estática, multi-hilo, mensaje mecanismo de paso (controlador)

5.3.1 Ejemplos de clase interna estática no estático =

  • Si no divulga la instancia causa estática clase interna creado = (ciclo de vida de la aplicación = ciclo de vida) estática, llevará a cabo una referencia a la forma predeterminada clase exterior debido a las clases internas no estáticos causadas por clase externa no puede ser liberado, llevando eventualmente a pérdidas de memoria

Es decir los objetos de clase estática exterior celebrada ejemplo clase interna no estática demuestra:

// 背景:
   a. 在启动频繁的Activity中,为了避免重复创建相同的数据资源,会在Activity内部创建一个非静态内部类的单例
   b. 每次启动Activity时都会使用该单例的数据

public class TestActivity extends AppCompatActivity {  

    // 非静态内部类的实例的引用
    // 注:设置为静态  
    public static InnerClass innerClass = null; 

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);   

        // 保证非静态内部类的实例只有1个
        if (innerClass == null)
            innerClass = new InnerClass();
    }

    // 非静态内部类的定义    
    private class InnerClass {        
        //...
    }
}

// 造成内存泄露的原因:
    // a. 当TestActivity销毁时,因非静态内部类单例的引用(innerClass)的生命周期 = 应用App的生命周期、持有外部类TestActivity的引用
    // b. 故 TestActivity无法被GC回收,从而导致内存泄漏
  • soluciones
  1. Las clases internas no estáticos SET: clase interna estática (clases internas estáticas no tienen la referencia predeterminada la clase externa)
  2. La clase interna se extrajo en una única realización paquete
  3. Trate de evitar las clases internas no estáticos crear instancias = static

Para usar el contexto, Solicitud de Contexto recomendada

5.3.2 multihilo: AsyncTask, implementar Ejecutable, clase Thread herencia

  • Usar el conocimiento reserva multihilo = clases internas no estáticos / clases anónimas, es decir hilo clase es una clases internas / clase no estático anónimo
  • Cuando la razón por la fuga de subproceso de trabajo es el procesamiento de tareas y de clase externo a ser destruidos debido a la clase de los trabajadores en la celebración de la referencia externa permitirá clase externa recolector de basura (GC) no pueden ser reciclados, lo que resulta en una pérdida de memoria

El principal uso de multi-threading es: AsyncTask, implementar Ejecutable y hereda el mismo principio antes de la clase de 3 Tema pérdidas de memoria, sobre todo con el fin de heredar la clase Thread aquí como un ejemplo

Los ejemplos de presentación

/** 
     * 方式1:新建Thread子类(内部类)
     */  
        public class MainActivity extends AppCompatActivity {

        public static final String TAG = "carson:";
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // 通过创建的内部类 实现多线程
            new MyThread().start();

        }
        // 自定义的Thread子类
        private class MyThread extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "执行了多线程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

   /** 
     * 方式2:匿名Thread内部类
     */ 
     public class MainActivity extends AppCompatActivity {

    public static final String TAG = "carson:";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 通过匿名内部类 实现多线程
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "执行了多线程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
}

/** 
  * 分析:内存泄露原因
  */ 
  // 工作线程Thread类属于非静态内部类 / 匿名内部类,运行时默认持有外部类的引用
  // 当工作线程运行时,若外部类MainActivity需销毁
  // 由于此时工作线程类实例持有外部类的引用,将使得外部类无法被垃圾回收器(GC)回收,从而造成 内存泄露
  • Las soluciones se pueden ver de lo anterior, hay dos condiciones claves causa pérdidas de memoria:
  1. Se hace referencia a la relación entre la "clase de trabajo ejemplo rosca exterior mantiene referencias a la"
  2. El ciclo de vida del trabajador ejemplo hilos> ciclo de vida de la clase externa, que subproceso de trabajo todavía se está ejecutando, mientras que las soluciones de clase externos necesitan destruir la idea = 1, de modo que las condiciones anteriores no se cumplen, ya sea para.
// 共有2个解决方案:静态内部类 & 当外部类结束生命周期时,强制结束线程
// 具体描述如下

   /** 
     * 解决方式1:静态内部类
     * 原理:静态内部类 不默认持有外部类的引用,从而使得 “工作线程实例 持有 外部类引用” 的引用关系 不复存在
     * 具体实现:将Thread的子类设置成 静态内部类
     */  
        public class MainActivity extends AppCompatActivity {

        public static final String TAG = "carson:";
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // 通过创建的内部类 实现多线程
            new MyThread().start();

        }
        // 分析1:自定义Thread子类
        // 设置为:静态内部类
        private static class MyThread extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "执行了多线程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

   /** 
     * 解决方案2:当外部类结束生命周期时,强制结束线程
     * 原理:使得 工作线程实例的生命周期 与 外部类的生命周期 同步
     * 具体实现:当 外部类(此处以Activity为例) 结束生命周期时(此时系统会调用onDestroy()),强制结束线程(调用stop())
     */ 
     @Override
    protected void onDestroy() {
        super.onDestroy();
        Thread.stop();
        // 外部类Activity生命周期结束时,强制结束线程
    }

5.3.3 mensaje mecanismo de paso de: HandlerAndroid pérdidas de memoria: razones detalladas y soluciones Handler Pérdida de memoria https://www.jianshu.com/p/031515d8a7ca

objeto 5,4 recurso no está cerrada después de su uso

  • Reveló las razones para el uso de los recursos (como BraodcastReceiver radio, archivo de flujo de archivos, una base de datos de cursor Cursor, recursos de imágenes de mapa de bits, etc.), si no destruido Actividad cierre oportuno / cancelación de estos recursos, no serán recuperados estos recursos, lo que resulta en la memoria fuga
  • Soluciones destruidos cuando la actividad a tiempo de cierre / cancelación de los recursos
// 对于 广播BraodcastReceiver:注销注册
unregisterReceiver()

// 对于 文件流File:关闭流
InputStream / OutputStream.close()

// 对于数据库游标cursor:使用后关闭游标
cursor.close()

// 对于 图片资源Bitmap:Android分配给图片的内存只有8M,若1个Bitmap对象占内存较多,当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存;最后再赋为null 
Bitmap.recycle();
Bitmap = null;

// 对于动画(属性动画)
// 将动画设置成无限循环播放repeatCount = “infinite”后
// 在Activity退出时记得停止动画

5.5 Otros usos

  • Además de estas cuatro situaciones comunes, y algo de uso diario puede conducir a pérdidas de memoria
  • Incluye: Contexto, WebView, adaptador, se detalla a continuación

imagen

5.6 resume a continuación, voy a resumir las razones de las pérdidas de memoria en Android con un mapa y Soluciones

6. El análisis herramienta asistida de pérdidas de memoria

  • Incluso entender completamente la causa de pérdidas de memoria, pero, inevitablemente, habrá una pérdida de memoria o fenómeno
  • El siguiente es un breve análisis de algunas de las herramientas de memoria de corriente de fuga son
  1. MAT (Herramientas de análisis de memoria)
  2. montón Visor
  3. Rastreador de asignación
  4. Android Studio 的 memoria del monitor
  5. LeakCanary

6.1 MAT (análisis de la memoria Herramientas)

  • Definición: una herramienta de análisis de memoria Eclipse montón de Java - >> Descargar
  • Papel: Ver el uso de la memoria actual

Mediante el análisis de la instantánea de memoria del análisis de procesos HPROF Java, rápidamente calcular el objeto en la memoria tamaño de la huella, ver qué objetos no pueden ser recogidos por la basura y se pueden visualizar de forma intuitiva ver objetos que pueden causar tales resultados

Uso específico: MAT Use Raiders

6.2 Montón Visor

Definición: El papel de un instrumento de análisis de memoria montón de Java: Ver la instantánea actual de la memoria

memoria de almacenamiento dinámico se puede ver de forma individual tiene una proporción total de diferentes tipos de datos y qué tipos de datos

Uso específico: Montón usuario utilice Raiders

6.3 Asignación Rastreador

Introducción: un efecto de memoria rastreo de las herramientas de análisis: el seguimiento de la información de asignación de memoria, el uso específico en secuencia: Asignación Rastreador usando Raiders

6.4 Monitor de Memoria

Descripción: Estudio Android viene con una herramienta gráfica para detectar efecto memoria: el seguimiento de las aplicaciones de uso del sistema / memoria. Las funciones básicas son las siguientes

imagen

Uso específico: Android Studio para utilizar el monitor de memoria Raiders

6.5 LeakCanary

Descripción: un cuadrado produce biblioteca de código abierto Android - >> Descargar papel: para detectar pérdidas de memoria uso específico: https://www.liaohuqiu.net/cn/posts/leak-canary/

7. Resumen

En este artículo se describe la naturaleza global de pérdidas de memoria, razón y solución, espero que trate de evitar una pérdida de memoria en el desarrollo

El artículo no es fácil, si te gusto este artículo, o para ayuda que espera mucha atención Oh pulgares hacia adelante. Los artículos serán actualizados continuamente. Absolutamente seco! ! !

Supongo que te gusta

Origin blog.51cto.com/14775360/2484779
Recomendado
Clasificación