Лучший способ узнать, куда идут ресурсы? - PullRequest
0 голосов
/ 13 мая 2011

У меня утечка памяти в моем приложении. Поэтому, естественно, я хочу это исправить. Проблема в том, что я либо не знаю, как использовать 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 на 221px, но, по-видимому, 19528kb. Если моя математика верна, 221 * 221 = 48841 * 4 = 195364 байт = 190,7 КБ. Это не имеет никакого смысла вообще. Во всяком случае, пожалуйста, посмотрите и посмотрите, что вы можете найти. Кстати, рассматриваемая строка с ошибкой следующая (из метода регенерации)

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

Ответы [ 2 ]

4 голосов
/ 14 мая 2011

Во-первых, я думаю, что сообщение Dalvik показывает неправильные единицы, тогда как ошибка GraphicsJNI верна:

dalvikvm E Недостаточно памяти: Размер кучи = 4871 КБ, Выделено = 2636 КБ, Размер растрового изображения = 19528 КБ2935
GraphicsJNI E ВМ не позволяет выделять 195364 байта

Имейте в виду, что вы можете обнаружить ошибку памяти:

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

Если ваши битовые карты всегда одинаковыразмер, я бы порекомендовал повторно их использовать.Если вы создаете и уничтожаете растровые изображения довольно быстро, вы рискуете опередить сборщик мусора и попасть в это состояние.

- Правка - Что касается исходного вопроса.Я обычно делаю следующее при поиске утечки памяти:

Шаги инициализации

  1. Убедитесь, что ваше приложение настроено для отладки в манифесте
  2. Запустите приложение, откройте DDMS и выберите приложение.
  3. Выберите представление «Отслеживание распределения» и запустите отслеживание

Анализ

  1. Пусть ваше приложение запустится или выполнит некоторые конкретные действия в вашем приложении, которые вызывают проблемы с памятью.
  2. Нажмите «Get Allocations», чтобы обновить трекер.Теперь вы можете остановить отслеживание, если хотите.
  3. В фильтре введите имя своего приложения, чтобы сузить результаты.

Вам необходимо подумать о том, что вы видите здесь иэто имеет смысл для вашего приложения.Должны ли быть тысячи небольших выделений памяти?Скорее всего нет.На этом этапе вы можете щелкнуть выделение и посмотреть, какой именно метод и номер строки вызывает выделение.

Другой способ - включить обновления кучи для вашего приложения и использовать проводник кучи для отслеживания выделений.Исследователь кучи не сообщает вам , откуда выделение, но он скажет вам следующее:

Количество выделений 1k растет и никогда не уменьшается.

Затем вы можете перейти в Allocation Tracker и отсортировать распределения по размеру, чтобы увидеть, где вы выполняете распределения 1k.

0 голосов
/ 13 мая 2011

Мне нравится использовать инструмент отслеживания выделения.

http://android -developers.blogspot.com / 2009/02 / трек-память allocations.html


Я понимаю, что это не то, о чем вы спрашивали ...

Я обнаружил, что стоит прочитать следующую документацию по утечкам памяти в Android.

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

... а также другие посты по оптимизации на http://android -developers.blogspot.com / search / label / Optimization

...