[セットトップ]Androidメモリオーバーフロー防止の概要


Androidの仮想マシンはレジスタベースのDalvikで、その最大スタックサイズは一般的に16 Mです.しかしAndroidはJava言語で作成されているため、AndroidのメモリメカニズムはJavaのメモリメカニズムに相当し、開発が始まったばかりの頃はメモリの制限問題がメモリオーバーフローなど深刻な問題をもたらしていました.メモリを使用しない場合は、Androidや他のプラットフォームで他のプログラムを実行する際に必要な状態を保存し、デッドプロセスによるメモリの問題をできるだけオフにしたり、ステータスを保存したりするときに解放したりすることで、システムの稼働面でのスムーズ性を高めることができます.
Androidのメモリは主に以下のように表現されています.
1.Androidプラットフォームでは、長期にわたっていくつかのリソースの参照を維持し、メモリを解放できないため、メモリの漏洩の問題が多い.例:Context(以下、ActivityはContext)では、最初のクラスオブジェクトの状態を維持し、他のクラスオブジェクトに状態を転送する必要がある場合は、最初のクラスオブジェクトを削除する前に、受信したクラスオブジェクトを解放する必要があります.JavaまたはAndroidメモリメカニズムでは、頂点のノードが解放される前に他のオブジェクトを保証しなければならないため、注意してください.システムGCによって回収解放されるには呼び出しがありません.@Override protected void onCreate(Bundle state){super.onCreate(state);TextViewlabel=new TextView(this);label.setText("Leaksare bad");setContentView(label);
@Override
protected void onCreate(Bundle state) {
     super.onCreate(state);
     TextViewlabel = new TextView(this);
     label.setText("Leaksare bad");
     setContentView(label);
}

 
このコードは、実行中のActivityにTextViewのインスタンスをロードすることを意味します.(Context)では、GC回収メカニズムにより、Contextを解放するには、まず引用したオブジェクトの一部を解放しなければならないことを知っています.もしそうでなければ、Contextを解放しようとすると、大量のメモリオーバーフローが発見されます.だから、うっかりメモリオーバーフローは非常に容易なことです.オブジェクトを保存すると、同時にメモリの漏洩.最も簡単な例として、ビットマップ(Bitmap)などがあります.たとえば、画面が回転すると、現在保持されているActivity状態が破壊され、新しいActivity状態が保存されるまで新しいActivityの生成が再申請されます.コード:privatestatic Drawable sBackground;@Override protected void onCreate(Bundle state){super.onCreate(state)}; TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground =getDrawable(R.drawable.large_bitmap); } label.setBackgroundDrawable(sBackground); setContentView(label); }
privatestatic Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");

if (sBackground == null) {
     sBackground =getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}

 
このコードは非常に速いと同時にエラーです.メモリの漏洩は、画面の移行方向に容易に現れます.Contextというインスタンスが表示されていないことがわかりますが、描画した図を1つのビューに接続すると、DrawableはViewにコールバックに設定されます.これは、上記のコードでは、実際にTextViewをアクティブに描画するときに、このActivityを参照していることを示しています.リンク状況は、Drawable->TextView->Contextと表現できます.
だからContextを解放しようとすると、実はメモリに保存されていて、解放されていません.
このような状況をどのように避けるか:主に.スレッドが最もエラーしやすい.スレッドを軽視しないでください.Androidではスレッドが最もメモリ漏れを起こしやすいです.スレッドがメモリ漏洩を生じる主な原因は、スレッドのライフサイクルが制御できないことです.次のコードがあります.
  publicclass MyTest extends Activity { @Override publicvoid onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new MyThread().start(); } privateclass MyThread extends Thread{ @Override public void run() { super.run();//do somthing } } }
publicclass MyTest extends Activity {
    @Override
    publicvoid onCreate(BundlesavedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        new MyThread().start();
    }
 
    privateclass MyThread extends Thread{
        @Override
        public void run() {
            super.run();
            //do somthing
        }
    }
}

 
コードは簡単ですが、Androidでまた新しい問題が来て、ビュー画面を切り替えると(横長スクリーン)では、横長スクリーンまたは縦長スクリーンのActivityが再構築されます.以前に作成したActivityは回収されるとイメージしていますが、事実はどうでしょうか.Javaメカニズムはあなたに同じ感じを与えません.Activityを解放する前にrun関数が終了していないため、MyThreadは破棄されていないので、そのActivityを引用します(Mytest)も破棄されていないため、メモリ漏洩の問題も発生しています.
Androidで提供されるAsyncTaskが好きな人もいますが、実際にはAsyncTaskの問題はさらに深刻で、Threadはrun関数が終了しない場合にのみこのようなメモリ漏洩問題が発生しますが、AsyncTask内部の実装メカニズムはThreadPoolExcutorを運用しており、このクラスで発生したThread対象のライフサイクルは不確定で、アプリケーションでは制御できません.したがって、AsyncTaskがActivityの内部クラスとして機能すると、メモリ漏洩の問題が発生しやすくなります.
スレッドの問題の改善方法は主に次のとおりです.
lスレッドの内部クラスを静的内部クラスに変更する.
lプログラムではなるべく弱引用でContextを保存する.
2.万悪のbitmap...
Bitmapは非常に悪いオブジェクトであり、メモリオブジェクトのメモリが大きすぎると、システムのメモリ制限を超えたときにメモリ漏洩の問題が明らかになります.
bitmapの解決は主にメモリにできるだけ保存しないか、サンプリングレートを小さくすることです.多くの場合、私たちの画像の画素が高いため、携帯電話の画面サイズにとって私たちはそんなに高い画素の割合の画像をロードする必要はありません.まず、画像のサンプリング率を元のUI操作に下げることができます.
bitmapオブジェクトのリファレンスを保存する必要がない場合は、ソフトインデックスで置き換えることもできます.具体的なインスタンスコードgoogleにもたくさんあります.
以上のように、メモリの漏洩を回避するには、主に以下の点に従います.
第一に、Contextのリファレンスを長期保存しないでください(Contextを参照するには、リファレンスオブジェクトとそれ自体のライフサイクルが一致するようにします).
第二に、Contextを使用する場合は、できるだけContextの代わりにApplicationContextを使用します.ApplicationContextのライフサイクルが長いため、参照の場合メモリ漏洩の問題はありません.
第三に、オブジェクトのライフサイクルを制御しない場合は、Activityでstatic変数を使用しないでください.できるだけWeakReferenceを使ってstaticの代わりにします.
第四に、ゴミ回収器はメモリを正確に回収することを保証していない.このように、自分の必要な内容を使用するとき、主なライフサイクルと不要な対象をタイムリーに解放する.Activityのライフサイクルが終わると、onDestroyで私たちが参照している他のオブジェクトを解放します.例えば、cursor.close().
実際には、より少ないコードを使用してプログラムを完了することができます.例えば、9 patch画像などを多く使うことができます.メモリの問題を発見し、掘り起こす価値のある詳細がたくさんあります.C/C++プログラムの「誰が作成し、誰が解放するか」の原則を実現できれば、JavaやAndroid自体のGCメカニズムよりもメモリの把握が悪くなく、メモリをよりよく制御し、携帯電話をよりスムーズに動作させることができます.