Androidでのメモリ漏洩とメモリオーバーフローの問題


メモリリークは簡単に言えばメモリスペースを申請し、使用後は解放されなかった.その一般的な表現は、プログラムの実行時間が長ければ長いほど、メモリの消費量が多くなり、最終的にすべてのメモリを使い果たし、システム全体がクラッシュすることです.プログラムによって申請されたメモリの1つで、ポインタが1つも指定されていないと、このメモリが漏れてしまいます.ユーザがプログラムを使用する観点から,メモリ漏洩自体に危害は生じず,一般のユーザとしてはメモリ漏洩の存在を全く感じない.本当に危害があるのはメモリの漏れの積み重ねで、これは最終的にシステムのすべてのメモリを消耗します.この観点から、使い捨てメモリの漏洩には危害はありません.堆積しないため、暗黙的なメモリの漏洩の危害性は非常に大きく、常発性と偶発的なメモリの漏洩よりも検出しにくいからです.
Androidアプリケーションのメモリ漏洩の原因は以下のとおりです:1データベースを問合せた後にカーソルcursor 2を閉じてAdapterを構築していない場合、convertViewを使用して3 Bitmapオブジェクトを再利用していない場合、使用時にrecycle()を呼び出してメモリ4オブジェクトを解放してライフサイクルの長いオブジェクトに参照されます.Activityが静的セットによって参照されると、Activityがメモリ漏洩の検出を解放できない場合:DDMSのheapツールを使用して、メモリオーバーフローがあるかどうかを検出します.
メモリリークの解決方法:メモリ分析ツールMAT(Memory Analyzer Tool)を使用して、メモリリークの対象を特定します.
アンドロイドの仮想マシンはレジスタベースのDalvikであり、その最大スタックサイズは一般的に16 Mである.しかし、AndroidはJava言語の作成を採用しているので、AndroidのメモリメカニズムはJavaのメモリメカニズムと大きく等しく、開発が始まったばかりの頃、メモリの制限問題はメモリオーバーフローなどの深刻な問題をもたらします.メモリを使用しない場合は、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);

  }

このコードは、TextViewのインスタンスを実行中のActivity(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);

  }

このコードは非常に速いと同時にエラーです.メモリの漏洩は、画面の移行方向に容易に現れます.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

  }

  }

  }

コードは簡単ですが、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メカニズムよりもメモリの把握が悪くなく、メモリをよりよく制御し、携帯電話をよりスムーズに動作させることができます.