Ошибка нехватки памяти в Android из-за увеличения размера кучи - PullRequest
13 голосов
/ 22 марта 2012

Я получаю из-за ошибки памяти.Я работаю над приложением чата.Он работает нормально, но когда я запускаю приложение на устройстве от 1 до 2 часов, размер кучи увеличивается, а когда он достигает 16 МБ, приложение начинает зависать и зависать через некоторое время и отображать out of memory due to heap size, потому что результирующий размер кучи равенбольше выделенного.

Я тестирую свое приложение в HTC Explorer.В моем приложении большинство операций использует фоновый поток, и для этого я использую Asnyc Task.

Я получаю сообщение об ошибке, подобное следующему.

04-30 16:53:14.658: E/AndroidRuntime(5707): FATAL EXCEPTION: MagentoBackground
04-30 16:53:14.658: E/AndroidRuntime(5707): java.lang.OutOfMemoryError: (Heap Size=20167KB, Allocated=16063KB, Bitmap Size=355KB)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.util.ByteArrayBuffer.<init>(ByteArrayBuffer.java:53)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:82)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:98)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:173)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at com.live2support.CustomHttpClient.executeHttpPost1(CustomHttpClient.java:163)

Isли предел размера кучи?как я могу решить мою проблему?

Ответы [ 5 ]

12 голосов
/ 09 мая 2012

Ваш вопрос состоит из двух частей:

1) Как определить размер кучи на моем тестовом устройстве?

2) Почему мое приложение превышает размер моей кучи?

Что касается вопроса 1, вы можете определить размер кучи на тестовом устройстве непосредственно в своем коде, позвонив по номеру:

Runtime.getRuntime () maxMemory ();.

См. этот пост для получения дополнительной информации об этом методе, а также некоторые примеры размеров кучи, доступных на различных устройствах.

Кроме того, если вы работаете с рутованным устройством, может быть способ напрямую установить (и проверить) размер кучи через интерфейс. Например, в различных версиях Android CyanogenMod в меню «Настройки» вы можете выбрать «Настройки CyanogenMod», затем «Производительность», а затем «Размер кучи виртуальной машины» и напрямую просмотреть (и изменить) размер кучи для вашего устройства. , Будьте осторожны, так как установка слишком маленького размера кучи может привести к неправильной работе вашего устройства или к худшему.

Относительно вопроса 2: Вы не предоставили достаточно информации для диагностики вашей конкретной проблемы, и в любом случае постановка такого диагноза из вторых рук в лучшем случае затруднительна. Лучшим решением для решения этой проблемы (и для изучения чего-то, что имеет непреходящее значение в процессе) будет знакомство с некоторыми из очень мощных инструментов анализа памяти, доступных в Android (некоторые из которых также интегрированы в Eclipse IDE). Я использую эти инструменты из Eclipse, поэтому я опишу их ниже.

Прежде всего, убедитесь, что ваша версия Eclipse обновлена, установив последнюю версию Eclipse (например, Indigo).

Далее в Eclipse выберите «Справка / Установка нового программного обеспечения», затем щелкните раскрывающийся список вверху и выберите

"Indigo - http://download.eclipse.org/releases/indigo"

Затем откройте категорию «Инструменты общего назначения», щелкнув знак «плюс» рядом с ней, и выберите «Анализатор памяти», а также «Анализатор памяти (диаграммы)» [необязательно]. Установите эти инструменты.

Далее выберите «Окно / Настройки», а затем «Android / DDMS» и выберите действие HPROF «Открыть в Eclipse». Это приведет к тому, что любой файл дампа кучи HPROF, созданный вами из DDMS, будет иметь соответствующий формат для Eclipse, а также автоматически откроет его в анализаторе памяти Eclipse (который был только что установлен выше).

Теперь откройте DDMS, выбрав Окно / Открыть перспективу / Другое / DDMS. Выберите значок «Устройства» (выглядит как телефон) слева и перетащите получившееся окно так, чтобы оно было где-то пристыковано, чтобы его было легко увидеть.

Убедитесь, что ваше устройство подключено к ПК через USB и ваше приложение работает.

На только что созданной вкладке «Устройства» выберите процесс запущенного приложения. Запустите приложение так, чтобы оно заняло достаточно памяти, чтобы вы знали, что оно просочилось, но не настолько, чтобы оно зависало. Теперь щелкните значок «Файл дампа HPROF» на вкладке «Устройства». После небольшой задержки вам будет предложен выбор отчетов в куче. Попробуйте Отчет о подозреваемых утечках, чтобы начать. Этот отчет откроется в инструменте анализа памяти. Он говорит вам, где ваше приложение использует память. Проверьте различные типы объектов и посмотрите, не выглядят ли они раздутыми относительно объема данных, который, как вы ожидаете, им потребуется; если это так, это может указывать на утечку.

Здесь - это хорошее руководство, более подробно описывающее, как сгенерировать и исследовать вашу кучу, используя DDMS и инструмент Memory Analyzer Tool.

Вернувшись в DDMS (или в перспективу DDMS в Eclipse), вы можете выбрать вкладку Allocation Tracker, когда ваше устройство подключено, а затем ваше устройство на вкладке устройств и затем выбрать процесс вашего приложения из списка для этого устройства. Затем на вкладке «Отслеживание распределения» нажмите кнопку «Начать отслеживание», затем запустите соответствующие операции вашего приложения (те, которые, как вы подозреваете, просочились), затем нажмите кнопку «Получить выделения» и нажмите кнопку «Остановить отслеживание».

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

7 голосов
/ 02 мая 2012

Похоже на классическую утечку памяти. Вы говорите, что используете AsyncTask для подключения. С помощью AsyncTask очень легко просочиться в контекст изменений конфигурации (например, ротации устройства), если вы не знаете, как правильно его использовать.

Во-первых, я настоятельно рекомендую вам посмотреть это: http://www.youtube.com/watch?v=_CruQY55HOk

Чтобы проверить, есть ли у вас такая утечка памяти, поверните устройство и проверьте, как ведет себя сборщик мусора. Вы должны иметь что-то вроде GC_... freed 211K, 71% free 300K/1024K, external 0K/0K, paused 1ms+1ms в вашем LogCat почти каждый раз, когда вы поворачиваете. Следите за изменениями в этой части: 300K/1024K. Если у вас нет утечек памяти, первая часть должна увеличиваться, а затем уменьшаться после нескольких сборок мусора. Если у вас есть утечка памяти, она будет расти и расти, вплоть до ошибки OOM.

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

Моя личная ставка была бы плохой реализацией AsyncTask - вы отсоединяете ее от уничтоженной активности и присоединяете ее к новой? Если нет, начните делать это (есть отличный пример от CommonsWare) или переключитесь на AsyncTaskLoader, который делает это за вас и, как правило, является отличной заменой AsyncTask (не только для загрузки материала).

4 голосов
/ 26 февраля 2016

Просто добавьте android:largeHeap="true" в тег приложения в ваших манифестах.

1 голос
/ 02 мая 2012

Ограничение размера кучи зависит от устройства. На устройстве 2.x я ожидаю, что около 20 или 32 МБ - это ваш лимит. См. Размер кучи Android на разных телефонах / устройствах и версиях ОС для получения дополнительной информации о размерах кучи.

По вашей трассировке стека, похоже, что com.live2support.CustomHttpClient.executeHttpPost1() находится в центре вашей проблемы.

0 голосов
/ 06 декабря 2013

Это можно сделать двумя способами в зависимости от вашей ОС Android.

  1. Вы можете использовать android:largeHeap="true" в теге приложения манифеста Android, чтобы запросить больший размер кучи, но это не будет работать на любых устройствах до Honeycomb.
  2. На устройствах до 2.3 вы можете использовать VMRuntime класс , но это не будет работать на Gingerbread и выше. Ниже описано, как это сделать.
VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE);

Перед настройкой HeapSize убедитесь, что вы ввели соответствующий размер, который не повлияет на другие функции приложения или ОС. Перед настройкой просто проверьте, какой размер занимает ваше приложение, а затем установите размер, чтобы выполнить свою работу. Не используйте так много памяти, иначе могут повлиять другие приложения.

Ссылка: http://dwij.co.in/increase-heap-size-of-android-application

...