0

アプリでメモリ リークが発生しました。だから直してあげたいと思うのは当然です。問題は、DDMS とメモリ割り当てツールの使用方法がわからないか、それらががらくた (またはその両方) であることです。そのため、すべてのリソースがどこで使用されているかを把握できる別の方法があるかどうか、または誰かが DDMS ツールの使用方法について教えてくれるかどうか疑問に思っています。

PS: はい、DDMS のデバッグ ボタンをクリックして、HPROF ダンプを発生させたり、[ヒープの更新] ボタンを使用して GC を実行したりする必要があることはわかっています。両方の詳細を表示できますが、作成したオブジェクトは表示されません。要するに、私は自分が見ているものを読むことができません。

どんな助けや啓発も大歓迎です。

〜エイドン

編集1:

カスタム ビューの描画方法全体にログを追加しました。いくつかの実験の後、メモリ リークの継ぎ目がこの方法に起因することがわかりました。

/** バックグラウンドのゲージに依存しない静的バッファ キャッシュを更新します。*/

private void regenerate() {
    mNeedRegen = false;
    // Prevent memory leaks by disposing of old bitmaps.
    if (mBackground != null) { mBackground.recycle(); mBackground = null; }
    // Our new drawing area
    Log.d(TAG, getWidth() + "\t" + getHeight());
    mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas backCanvas = new Canvas(mBackground);
    float scale = (float)getWidth();
    backCanvas.scale(scale, scale);
    drawRim(backCanvas);
    drawFace(backCanvas);
    drawTitle(backCanvas);
    if (!(this instanceof EmptySpace)) { drawGroupIcon(backCanvas); }
    regenerateBackground(backCanvas);
}

アプリをいじった後、このエラーを引き起こすことができました:

     dalvikvm-heap  E  195364-byte external allocation too large for this process.
  2935               dalvikvm  E  Out of memory: Heap Size=4871KB, Allocated=2636KB, Bitmap Size=19528KB
  2935            GraphicsJNI  E  VM won't let us allocate 195364 bytes
  2935         AndroidRuntime  D  Shutting down VM
  2935               dalvikvm  W  threadid=1: thread exiting with uncaught exception (group=0x400259f8)
  2935         AndroidRuntime  E  FATAL EXCEPTION: main
  2935         AndroidRuntime  E  java.lang.OutOfMemoryError: bitmap size exceeds VM budget
  2935         AndroidRuntime  E    at android.graphics.Bitmap.nativeCreate(Native Method)
  2935         AndroidRuntime  E    at android.graphics.Bitmap.createBitmap(Bitmap.java:574)
  2935         AndroidRuntime  E    at com.android.appion.arm.widgets.GaugeBase.regenerate(GaugeBase.java:239)
  2935         AndroidRuntime  E    at com.android.appion.arm.widgets.GaugeBase.onSizeChanged(GaugeBase.java:86)
  2935         AndroidRuntime  E    at android.view.View.setFrame(View.java:7101)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7028)
  2935         AndroidRuntime  E    at android.widget.GridView.setupChild(GridView.java:1316)
  2935         AndroidRuntime  E    at android.widget.GridView.makeAndAddView(GridView.java:1222)
  2935         AndroidRuntime  E    at android.widget.GridView.makeRow(GridView.java:265)
  2935         AndroidRuntime  E    at android.widget.GridView.fillSpecific(GridView.java:463)
  2935         AndroidRuntime  E    at android.widget.GridView.layoutChildren(GridView.java:1122)
  2935         AndroidRuntime  E    at android.widget.AbsListView.onLayout(AbsListView.java:1147)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.SlidingDrawer.onLayout(SlidingDrawer.java:331)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:909)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.view.ViewRoot.performTraversals(ViewRoot.java:1049)
  2935         AndroidRuntime  E    at android.view.ViewRoot.handleMessage(ViewRoot.java:1744)
  2935         AndroidRuntime  E    at android.os.Handler.dispatchMessage(Handler.java:99)
  2935         AndroidRuntime  E    at android.os.Looper.loop(Looper.java:144)
  2935         AndroidRuntime  E    at android.app.ActivityThread.main(ActivityThread.java:4937)
  2935         AndroidRuntime  E    at java.lang.reflect.Method.invokeNative(Native Method)
  2935         AndroidRuntime  E    at java.lang.reflect.Method.invoke(Method.java:521)
  2935         AndroidRuntime  E    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
  2935         AndroidRuntime  E    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
  2935         AndroidRuntime  E    at dalvik.system.NativeStart.main(Native Method)

エラー自体は理にかなっています。メモリが不足しました。意味をなさないのは、私が作成しようとしているビットマップが 221px x 221px であることですが、明らかに 19528kb です。私の計算が正しければ、221 * 221 = 48841 * 4 = 195364バイト= 190.7kb です。これはまったく意味がありません。どなたでも、ぜひご覧ください。ところで、エラーからの問題の行は次のとおりです(regenerateメソッドから)

mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
4

2 に答える 2

4

まず、Dalvikメッセージが間違った単位を示しているのに対し、GraphicsJNIエラーは正しいと思います。

dalvikvm Eメモリ不足:ヒープサイズ= 4871KB、割り当て済み= 2636KB、ビットマップサイズ= 19528KB 2935
GraphicsJNIEVMでは195364バイトを割り当てられません

メモリエラーをキャッチできることに注意してください。

try{
    mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
} catch(OutOfMemoryError e){
    //do something
}

ビットマップが常に同じサイズである場合は、それらを再利用することをお勧めします。ビットマップの作成と破棄をかなり迅速に行うと、ガベージコレクターのペースを上回り、この状態になるリスクがあります。

-編集-元の質問について。私は通常、メモリリークを探すときに次のことを行います。

初期化手順

  1. マニフェストでアプリがデバッグ可能に設定されていることを確認します
  2. アプリを起動し、DDMSを開いて、アプリケーションを選択します。
  3. 割り当てトラッカービューを選択し、追跡を開始します

分析

  1. アプリを実行するか、メモリの問題を引き起こしているアプリ内の特定のアクティビティを実行します。
  2. 「割り当ての取得」をクリックして、トラッカーを更新します。必要に応じて、追跡を停止できるようになりました。
  3. フィルタにアプリケーション名を入力して、結果を絞り込みます。

ここで何を見ているのか、そしてそれがアプリケーションにとって意味があるのか​​どうかを考える必要があります。何千もの小さなメモリ割り当てが必要ですか?ほとんどの場合、そうではありません。この時点で、割り当てをクリックして、割り当ての原因となっているメソッドと行番号を正確に確認できます。

もう1つの方法は、アプリのヒープ更新を有効にし、ヒープエクスプローラーを使用して割り当てを追跡することです。ヒープエクスプローラーは、割り当てがどこから来ているかを教えてくれませんが、たとえば次のように教えてくれます。

1kの割り当ての数は増え続けており、決して減ることはありません。

次に、割り当てトラッカーに移動し、サイズで割り当てを並べ替えて、1,000の割り当てを実行している場所を確認できます。

于 2011-05-14T00:09:48.610 に答える
0

割り当てトラッカー ツールを使用するのが好きです。

http://android-developers.blogspot.com/2009/02/track-memory-allocations.html


これはあなたが求めていたものではないことに気づきました...

Android のメモリ リークに関する次のドキュメントは、読む価値があることがわかりました。

http://developer.android.com/resources/articles/avoiding-memory-leaks.html

...およびhttp://android-developers.blogspot.com/search/label/Optimizationの最適化に関する他の投稿

于 2011-05-13T18:52:52.573 に答える