Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

Recommander la collecte, ils peuvent par ailleurs pas le trouver! ! !

avant-propos

Dans Android, le phénomène des fuites de mémoire sont communs, et les conséquences résultant fuite de mémoire fera l'application crash Dans cet article, une introduction complète à la nature des fuites de mémoire, la raison et la solution, fournissant finalement un certain outil d'analyse des fuites de mémoire commune, espérons qu'il vous plaira.

annuaire

image

1. introduction

Ce ML (fuite de mémoire) désigne le phénomène dans la mémoire de programme d'application, lorsque la mémoire n'a pas besoin d'utiliser, mais ne peut pas être retourné au programme publié &

2. L'impact de l'application

Facile à faire déborder de la mémoire d'application, que le débordement de mémoire OOM Description:

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

3. La nature de la cause des fuites de mémoire se produisent

Description spécifique

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

  • Une attention particulière du point de vue du mécanisme, car la présence de la collecte des ordures Java (le GC), une fuite de mémoire ne devrait pas exister, fuite de mémoire se produit parce que les causes humaines de maintien externe = involontairement référence d'objet détenus par une telle référence cycle de vie> cycle de vie de référence

4. Base de connaissances: mécanisme de gestion de la mémoire Android

4.1 introduction

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

Ensuite, pour le processus de récupération, l'allocation de mémoire d'objet variable et recyclage expliquer en détail

4.2 pour le processus des stratégies de mémoire . Une stratégie d'allocation de mémoire par le ActivityManagerService gérer de manière centralisée les allocations de mémoire pour tous les processus b stratégie récupération de la mémoire Étape 1: Application Framework type de processus de décision Android récupéré dans le processus est hébergé, lorsque l'espace de processus est serré, il le fera. procédé selon la faible priorité - >> ordre élevé processus de récupération automatique Android du processus en cinq niveaux de priorité, comme suit:

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

Étape 2: processus réel de récupération Linux ActivityManagerService score spécifique pour tous les processus (score stocké dans la variable adj) score de mettre à jour le noyau Linux noyau Linux se fait en vraie récupération de la mémoire

Résumer ici que les processus, ce qui complique le processus, les lecteurs intéressés peuvent faire des recherches de code source système ActivityManagerService.java

4.2 pour les objets, les variables, les stratégies de mémoire

  • Android pour les objets, les variables, les stratégies de mémoire avec Java
  • = Objet allocation de gestion de la mémoire de la mémoire / variables désallocation +

Ci-dessous, nous allons parler plus l'allocation de mémoire de libération de la mémoire et la stratégie a. Stratégie d'allocation mémoire

  • objet d'allocation de mémoire variable / responsabilité automatique du programme
  • Il existe trois types: la distribution statique, pile de distribution, tas et distribution, respectivement, pour les variables statiques, variables locales et instance d'objet détaillé ci-dessous

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

REMARQUE: l'allocation de mémoire utilisée pour expliquer un exemple

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. stratégie de diffusion mémoire

  • objets de libération de mémoire / variables sont la responsabilité du collecteur des ordures Java (GC) / cadre pile
  • Ici principalement sur la répartition cible (qui est, la formule d'allocation tas) la stratégie de sortie de mémoire = Java garbage collector (GC)

Étant donné que l'allocation statique sans relâcher la pile par une distribution automatique uniquement cadre pile, pile, relativement simple, et donc pas décrit en détail

  • Java garbage collector (GC) libération de mémoire = algorithmes collecte des ordures, y compris:

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

détaillé ci-dessous

Android Optimisation des performances: Ali, Tencent et d'autres connaissances sur les fuites de mémoire sont ici!

5. Causes courantes des fuites de mémoire et solutions

conducteur commun à la mémoire des fuites principales raisons:

  1. collections
  2. variables statiques membres des mots-clés modifiés
  3. classes internes non statique / classe anonyme
  4. objet ressource n'est pas fermé après utilisation

Ci-dessous, je détaillerai pourquoi chaque fuites de mémoire de déclenchement

5.1 collections

  • Après avoir ajouté des éléments de mémoire, reportez-vous encore de divulguer les collections de motifs avec un objet élément de collection, faisant l'objet est une collection d'éléments ne peuvent pas être recyclés, ce qui entraîne dans un exemple de fuite de mémoire démontre:
// 通过 循环申请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 依然不可回收该对象
  • Après la classe de collecte de solution pour ajouter une collection d'éléments objets doivent être retirés de la collection après utilisation

Comme il y a un certain nombre d'éléments, donc la meilleure façon de vider = & objet de collection est définie sur null

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

5.2 Variables membres statiques modifiés mots-clés

  • réserve du cycle de vie des connaissances à modifier des mots-clés variable membre statique du cycle de vie de l'application =
  • Lorsque la raison de fuite Ruoshi a cité des exemples de variables membre mot-clé modifié statique de la consommation excessive de ressources (comme le contexte), elle est sujette à la durée de vie de la variable membre> citations exemple cycle de vie, lorsque les cas cités à la fin de cycle de vie de la destruction , en raison de tenir une variable statique et ne peut pas être récupéré, de sorte que la fuite de mémoire se produit des exemples pour expliquer:
public class ClassName {
 // 定义1个静态变量
 private static Context mContext;
 //...
// 引用的是Activity的context
 mContext = context; 

// 当Activity需销毁时,由于mContext = 静态 & 生命周期 = 应用程序的生命周期,故 Activity无法被回收,从而出现内存泄露
}
  • solutions
  1. Essayez d'éviter les variables membres statiques ont cité des cas de consommation excessive de ressources (comme le contexte)

Pour le contexte de référence, puis essayez d'utiliser le contexte applicaiton

  1. Utilisation de références faibles (WeakReference) tenue en place forte exemple de référence

Note: Il y a une variable membre statique exemple typique = singleton

  • Connaissance singleton puisque les caractéristiques statiques de la réserve, la longueur du cycle de vie du cycle de vie de l'application =
  • Si un objet de raison fuite ne ont pas besoin d'utiliser un seul mode de réalisation est également titulaire d'une référence d'objet à l'objet, l'objet ne sera pas correctement récupéré entraînant une fuite de mémoire

Des exemples de présentations:

// 创建单例时,需传入一个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;
    }
}
  • Cycle de vie Solutions objet singleton cycle de vie de l'application fait référence =

Dans l'exemple ci-dessus, l'application doit transférer contexte, parce que le cycle de vie = cycle de vie de l'application de l'application

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;
    }
}

5.3 classes internes non statiques / classe anonyme

  • Réserve des classes internes non statiques connaissances / default classe anonyme contient des références à la classe externe, et les classes internes ne sont pas statiques
  • Common Case 3 types, à savoir: Des exemples de classe interne statique = non statique, multi-thread, mécanisme de passage de messages (gestionnaire)

5.3.1 Exemples de classe interne statique non-statique =

  • Sinon divulguer l'instance statique cause classe interne créée = statique (l'application du cycle de vie = cycle de vie), tiendra une référence à la valeur par défaut de la classe externe en raison des classes internes non statiques causés par classe externe ne peut pas être libéré, conduisant éventuellement à des fuites de mémoire

Ce sont les objets statiques tenue de la classe externe par exemple de classe interne non statique démontre:

// 背景:
   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回收,从而导致内存泄漏
  • solutions
  1. Les classes internes non statiques définies: classe interne statique (classes internes statiques ne tiennent pas la référence par défaut la classe externe)
  2. La classe interne est extrait dans un seul mode de réalisation de l'emballage
  3. Essayez d'éviter les classes internes non statiques créent des instances = statique

Pour une utilisation Contexte, Application recommandée du contexte

5.3.2 multithreading: AsyncTask, mettre en œuvre Runnable, l'héritage classe Thread

  • Utiliser les connaissances réserve multithread = classes internes non statiques / classes anonymes, à savoir enfilez classe est une classe interne non statique / classe anonyme
  • Lorsque la raison de la fuite de thread de travail est des tâches de traitement et classe externe à détruire en raison de la catégorie des travailleurs en tenant la référence externe permettra éboueur de classe externe (GC) ne peuvent pas être recyclés, ce qui entraîne une fuite de mémoire

L'utilisation principale du multi-threading est: AsyncTask, mettre en œuvre Runnable et héritera le même principe avant les fuites de mémoire de fil de classe 3, principalement afin d'hériter de la classe Thread ici comme exemple

Des exemples de présentation

/** 
     * 方式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)回收,从而造成 内存泄露
  • Les solutions peuvent être vu de ce qui précède, il y a deux conditions clés provoquent des fuites de mémoire:
  1. Il est fait référence à la relation entre « instance de filetage extérieur de la classe ouvrière contient des références à » la
  2. Le cycle de vie des threads de travail instance> Cycle externe de vie de la classe, ce thread de travail est toujours en cours alors que les solutions de classe externes doivent détruire l'idée = 1, de sorte que les conditions ci-dessus ne sont pas remplies pour.
// 共有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 un message mécanisme passant: les fuites de mémoire: HandlerAndroid raisons détaillées et des solutions mémoire Handler fuite https://www.jianshu.com/p/031515d8a7ca

objet 5.4 des ressources n'est pas fermée après utilisation

  • Indiquer les raisons de l'utilisation des ressources (comme BraodcastReceiver radio, flux fichier fichier, une base de données curseur ressources image du curseur, Bitmap, etc.), sinon détruit la fermeture / annulation rapide activité de ces ressources, ces ressources ne seront pas récupérés, ce qui en mémoire fuite
  • Solutions détruites lorsque la fermeture / annulation rapide activité des ressources
// 对于 广播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 Autre utilisation

  • En plus de ces quatre situations courantes, et une utilisation quotidienne peut conduire à des fuites de mémoire
  • Inclure: Contexte, WebView, adaptateur, détaillé ci-dessous

image

5.6 résumées ci - dessous, je vais résumer les raisons de fuites de mémoire dans les applications avec une carte et solutions

6. L'analyse de l'outil assisté par des fuites de mémoire

  • Même bien comprendre la cause des fuites de mémoire, mais il y aura inévitablement une fuite de mémoire ou d'un phénomène
  • Ce qui suit est une analyse brève de quelques-uns des outils de fuite de mémoire grand public sont
  1. MAT (Outils d'analyse mémoire)
  2. Heap Viewer
  3. Suivi d'allocation
  4. Moniteur Mémoire Android studio
  5. LeakCanary

6.1 MAT (Outils d'analyse mémoire)

  • Définition: un outil d'analyse de la mémoire Eclipse Java Heap - >> Télécharger
  • Rôle: Voir l'utilisation actuelle de la mémoire

En analysant l'instantané de la mémoire de l'analyse des processus Java HPROF, calculer rapidement l'objet de la taille de l'empreinte mémoire, voir quels objets ne peuvent pas être des ordures collectées par et peuvent être visualisées voir intuitivement les objets qui peuvent causer de tels résultats

Utilisation spécifique: MAT Utilisez Raiders

6.2 Heap Viewer

Définition: d'un outil d'analyse de la mémoire Java Heap Rôle: Voir l'instantané actuelle de la mémoire

Mémoire segmentée peut être vu, individuellement, ont une proportion totale de différents types de données et quels types de données

Utilisation spécifique: Heap Viewer Utilisez Raiders

6.3 Tracker Allocation

Introduction: un outil d'analyse de l'effet mémoire de trace: le traçage des informations d'allocation de mémoire, l'utilisation spécifique en séquence: Allocation Tracker en utilisant Raiders

6.4 Moniteur Mémoire

Description: Android Studio est un outil graphique pour détecter l'effet mémoire: système de suivi / applications d'utilisation de la mémoire. Les fonctions de base sont comme suit

image

Utilisation spécifique: Android Studio pour utiliser les Raiders Memory Monitor

6.5 LeakCanary

Description: un carré produit Android bibliothèque open source - >> Télécharger rôle: pour détecter les fuites de mémoire utilisation spécifique: https://www.liaohuqiu.net/cn/posts/leak-canary/

7. Résumé

Cet article décrit la nature complète des fuites de mémoire, la raison et la solution, je l'espère vous essayez d'éviter une fuite de mémoire dans le développement

L'article n'est pas facile, si vous avez aimé cet article, ou pour vous aider à espérer beaucoup d'attention pouces Oh avant. Les articles seront continuellement mis à jour. Tout à fait sec! ! !

Je suppose que tu aimes

Origine blog.51cto.com/14775360/2484779
conseillé
Classement