メモリの漏洩が速やかに発生

6448 ワード

JAvaメモリ漏洩の基礎知識
JAvaメモリの割り当てポリシー
スタティツクアサイメント
  • 静的記憶領域は、メソッド領域とも呼ばれ、このメモリ領域には主に静的データ、グローバル変数などが格納されている.このメモリは、プログラムのコンパイル時に割り当てられ、静的記憶領域に格納された変数であり、プログラムの実行中に
  • が存在する.
  • スタック領域、メソッド実行時、メソッド内のローカル変数は、スタック上にメモリ空間を作成し、メソッド実行終了後、これらの変数が持つメモリは自動的に解放されます.スタックメモリ割り当て演算は、プロセッサに内蔵されているため、効率は高いですが、スタック領域のメモリ容量は
  • に限られています.
  • スタック領域は、ダイナミックメモリ割り当てとも呼ばれ、通常は私たちのnewオブジェクトから出たメモリであり、この部分に使用されていない場合はjavaのゴミ回収器によって回収されます.

  • スタック領域、スタック領域:スタック領域:メソッド内で定義された基本タイプの変数と、オブジェクトの参照変数はメソッドのスタックメモリに割り当てられ、メソッドで変数を定義するとjavaはスタック内でその変数にメモリ空間を割り当て、この変数の役割ドメインを超えると無効になり、割り当てられたメモリ空間が解放されます.この場合、スタック領域が以前に占めていたメモリ領域は他の方法で使用されます.ヒープ領域:newによって作成されたすべてのオブジェクトと配列を格納し、ヒープに割り当てられたメモリはjavaのゴミ回収器によって管理され、生成された1つの配列、またはオブジェクトは、スタックに特殊な変数、すなわち参照変数を定義してヒープ内のものにアクセスすることもできます.
    JAvaはメモリをどのように管理していますか
    JAvaメモリ管理は、オブジェクトの割り当てと解放の問題であり、newによってオブジェクトにメモリ空間を申請することで、すべてのオブジェクトがスタックに割り当てられ、gcは自動的に解放されます.プログラマーの作業を簡素化しましたが、javaの仮想的な作業が重くなったのもjavaが遅い理由の一つです.gcは、オブジェクトを正しく解放するために、オブジェクトの申請、参照、参照、コピーなど、各オブジェクトの動作状態を監視する必要があります.オブジェクトを有向図の頂点、参照関係を有向図のエッジ、プロセス頂点から始まる有向ルートツリー、有向図ではルート頂点が達できるオブジェクトはすべて有効なオブジェクトであり、ルート頂点が達できないオブジェクトは回収可能なオブジェクトである.
    JAvaでのメモリ漏洩
    メモリリークとは、不要なオブジェクトがメモリを占有し続けたり、不要なオブジェクトのメモリがタイムリーに解放されなかったりして、メモリ領域の浪費をメモリリークと呼ぶ
    Androidからメモリが漏れる
    シングル・ケース不適切なシングル・ケースの使用は、メモリの漏洩を引き起こす
      public class AppManager {
     //        :
     //private static AppManager instance;
    // private Context context;
    //    private AppManager(Context context) {
    //        this.context = context;
    //    }
    //    public static AppManager getInstance(Context context) {
    //        if (instance == null) {
    //            instance = new AppManager(context);
    //        }
    //        return instance;
    //    }
    //             :
    private static AppManager instance;
    private Context context;
    
    private AppManager(Context context) {
        this.context = context.getApplicationContext();//   Application  context
    }
    
    public static AppManager getInstance(Context context) {
        if (instance == null) {
            instance = new AppManager(context);
        }
        return instance;
      }
    }
    

    匿名の内部クラス非静的内部クラスはデフォルトで外部クラスの参照を持ち、静的内部クラスに設定する必要があります.
    handler handlerは非静的内部クラスです.解決:handlerを静的内部クラスに設定し、handlerの内部にactivity外部クラスの弱い参照を持つ.
    //メモリ漏れの原因となる書き方:
    //    private Handler mHandler = new Handler() {
    //        @Override
    //        public void handleMessage(Message msg) {
    //            //...
    //       }
     //    };
    //
    //    @Override
    //    protected void onCreate(Bundle savedInstanceState) {
    //        super.onCreate(savedInstanceState);
    //        setContentView(R.layout.activity_main);
    //        loadData();
    //    }
    //
    //    private void loadData() {
    //        //...request
    //        Message message = Message.obtain();
     //        mHandler.sendMessage(message);
     //    }
      //
      //    static class TestResource {
      //        private static final String TAG = "";
    //        //...
    //    }
    

    //メモリ漏洩の修復方法:
     ★import java.lang.ref.WeakReference;
    private MyHandler mHandler = new MyHandler(this);
    private TextView mTextView ;
    private static class MyHandler extends Handler {
        private WeakReference reference;
        public MyHandler(Context context) {
            reference = new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
    //            activity.mTextView.setText("");
            }
        }
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadData();
    }
    
    private void loadData() {
        //...request
        Message message = Message.obtain();
        mHandler.sendMessage(message);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
         mHandler.removeCallbacksAndMessages(null);
     }
     }
    

    staticメンバー変数の使用を避ける
    メンバー変数をstaticと宣言すると、彼のライフサイクルは、App全体のライフサイクルと一致し、Appプロセスが設計上常駐メモリである場合、Appがバックグラウンドに切断されても、この部分のstatic変数は解放されません.現在のApp内蔵管理メカニズムによると、メモリの大きいバックグラウンドプロセスは、優先的に回収されます.だから、プロセスが回収された後、あなたが保存している変数は安全ではありません.このような問題は,クラス設計の際に考慮し,初期化時に静的メンバとして設定するか,怠惰なロードを考慮することができるかどうかである.必ず使用する場合は、これらの変数のライフサイクルを管理する必要があります.
    リソースがシャットダウンされていないことによるメモリの漏洩使用ブロードキャスト、contenProvider、ドキュメント、カーソル、socket、Bitmap、ライフサイクルの破棄時に、これらのリソースをシャットダウンおよびログアウトします.
    AsyncTaskによるメモリ漏洩はhandlerと同様に、サイクル破棄を宣言する必要がある場合、cancle
    Bitmap c側のメモリ、recycle()が必要
    メモリ管理メカニズム
    オペレーティングシステムの観点から、メモリはデータ記憶領域であり、オペレーティングシステムによってスケジューリングされたリソースに属する.≪メモリの割当て|Assign Memory|emdw≫:オペレーティング・システムは、各プロセスに適切なメモリ・サイズを割り当て、各プロセスが正常に使用されることを保証します.回収メカニズム:オペレーティングシステムのメモリ回収メカニズムは、メモリが不足している場合に合理的な回収再分配の役割を果たす.
    Androidメモリ管理メカニズム
  • 割り当てメカニズムアンドロイドは、各プロセスにメモリを割り当てる際に、柔軟性のある割り当て方式を採用しています.つまり、システムが開始されると、このアプリにメモリをあまり割り当てるのではなく、APPプロセスごとに小額の量を割り当てるのですが、この小額の量はモバイルデバイスごとの物理RAMサイズによって決まります.Appが稼働するにつれて、現在のメモリが不足しているため、androidはappにより多くのメモリを割り当て続けます.もちろん限られています.要するにandroidシステムのメモリ割り当てメカニズムは、より多くのプロセスをメモリに保存することであり、ユーザーが次のAPPプロセスを起動すると、プロセスを再作成する必要はなく、既存のプロセスを復元すればよいので、体験が向上します.
  • 回収メカニズムandroidはメモリの使用を最大限に行い、Linuxの特徴を継承しています.システムがメモリ不足を発見すると、他のプロセスが殺されます.新しいプロセスにメモリを割り当てるので、優先順位のフロントプロセスが表示されます.プロセスサービスプロセスは、いくつかのサービスの最初の3つが殺されないバックグラウンドプロセスを開きます.キャッシュリストに保存され、データ構造はLRUで、リストの末尾にある空のプロセスを先に殺します.システムのパフォーマンスを比較するために、Androidはこれらのプロセスを保存しません.

  • Androidシステムがプロセスを殺し始めたとき、androidは常により多くのメモリを回収する傾向にあるため、システムはプロセスごとに殺した後の回収効果を判断します.もちろん、殺したほうが少ないほうがいいです.
    メモリ管理の目標
  • より少ない消費メモリ
  • 適切な時、合理的にシステム資源を解放する
  • 適切なライフサイクルにおいて、重要なデータ
  • を保存または復元する.
    メモリ最適化の方法
  • サービスは、タスクを完了したら、できるだけ停止します.彼は優先度の低いサービスプロセスなので、メモリ回収に影響し、サービスの代わりにIntentServiceを使用します.IntentServiceはサービス内部のオープンサブスレッドを継承し、時間のかかる操作を行い、自動的に終了することができます.サービスのように手動stopServiceではありません.
  • Uiが見えない場合、Uiだけが使用するリソースを解放し、OnTreeMemory()がAppにリソースの回収を通知する
  • がある.
  • メモリが不足している場合も、OnTreeMemory()でApp回収リソース
  • に通知します.
  • Bitmapにより、現在のデバイスの解像度に応じてbitmapが圧縮され、bitmapを使用した後にrecycle()を使用してcメモリが解放され、ソフトリファレンスが使用され、LRUが使用される.
  • は、hashmapのSparseArray、ArrayMapの代わりにメモリに対して最適化されたデータ構造を使用するとともに、できるだけ列挙を少なくし、消費メモリは定数の2倍の
  • である.
  • 依存注入フレームワークの使用を回避し、これらのフレームワークの使用は便利であるほか、スキャン注釈によるシステムリソース
  • をもたらす.
  • ZIP整列APK
  • を使用
  • は、マルチプロセス、ロケーション、push、webViewを使用します.もちろんマルチプロセスのセキュリティ、データ転送が難しいという問題
  • メモリオーバーフローVSメモリリーク
    メモリオーバーフローは、実際にはOOMなのか、bitmapなのか、例えば圧縮されていないbitmapなのか.圧縮しましょう、bitmapの属性を使って、裁断しましょう、回収しましょう.メモリ漏洩とは、ゴミ回収器gcのメモリが回収されていないことである.dump分析を一気に引っ張る.