LINUX.ORG.RU

OutOfMemoryError не могу победить

 , ,


0

2

Ошибка вроде как понятна, не хватает памяти, на моем телефоне все работает хорошо, но как начали проверять на бюджетном варианте телефона, то ошибка такая вылазит, когда я пытаюсь выбрать фотографию из телефона, размер картинки желательно сделать не меньше 960x960 (фотографии для галереи) но на такой размер постоянно ругается, если же сделать размер 250x250 то работает нормально, может быть как-то можно размер памяти увеличить, я так понял под приложение выделяется определенный размер памяти, который он не может превысить.

читаю вот этот цикл статей: http://developer.android.com/intl/ru/training/displaying-bitmaps/index.html

Но как-то не особо помогает, вроде следую всем рекомендациям, и в асинхронном потоке загружаю, но все равно эта ошибка.

Как загружаю: https://gist.github.com/sysint64/b4e7924fffa0c7d39a29

Caused by: java.lang.OutOfMemoryError: (Heap Size=46471KB, Allocated=30904KB)
     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:658)
     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:347)
     at theinvaders.metoyou.Utility.decodeSampledBitmapFromFile(Utility.java:298)
     at theinvaders.metoyou.tasks.BitmapWorkerTask.doInBackground(BitmapWorkerTask.java:38)
     at theinvaders.metoyou.tasks.BitmapWorkerTask.doInBackground(BitmapWorkerTask.java:13)
     at android.os.AsyncTask$2.call(AsyncTask.java:287)

★★★

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

vurdalak ★★★★★
()

И что, загружаешь одну картинку и сразу падает? 960x960 * 4B = 3MB << 46 MB. Что-то ты не договариваешь.

Quickern ★★
()

Java
много картинок грузятся асинхронно
garbage collector
out of memory

Остаётся только страдать.

Deleted
()
Ответ на: комментарий от Quickern

Сразу падает, на HTC One S, на HTC Desire 210 намного большего размера картинки если загружаю, все работает хорошо, не вылетает.

Int64 ★★★
() автор топика

Памяти в свой смартфон докупи, нищеброт.

// Так говорят Java-программисты, которые считают себя крутыми.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Я вот прямо сейчас проверил, на моем телефоне на 512 МБ оперативки меньше, но почему-то не вылетает с такой ошибкой, так почему на HTC One S вылетает?
Может в версии Android проблема?
HTC One S - Android 4.1.1
HTC Desire 210 - Android 4.2.2

Int64 ★★★
() автор топика

Попробуйте использовать вот такой BitmapFactory.Options (у вас он на строке №3 создаётся):

    public static BitmapFactory.Options getOptions() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        options.inDither = true;
        options.inSampleSize = 2;
        return options;
    }
Если изображений действительно много и памяти всё равно не хватает, модифицируйте манифест, добавив largeHeap в application:
    <application
        ...
        android:largeHeap="true">
Но это если действительно нет выхода.

Weres ★★★
()
Ответ на: комментарий от EXL

хехе)))
тут же другой кейс немного. Разрабатывать мобильные приложения - это не ковырять ынтерпрайз поделия.
Яб начал с профайлера.

ii8_ ★★★★
()
Ответ на: комментарий от Int64

Ты должен понимать OutOfMemory может выпадать не только из-за твоего приложения. Здесь нужно посмотреть на соседей, сколько они жрут и чё требуют.

ii8_ ★★★★
()
Ответ на: комментарий от ii8_

Каждому приложению в андроид выделяется определенное количество памяти. Если для активного приложения памяти не хватает - система заберет память у неактивных. Вы встречались с OutOfMemory из-за других приложений на практике?

Weres ★★★
()
Ответ на: комментарий от rezedent12

А вот и коммипетух со смишными картинками прибежал.

anonymous
()
Ответ на: комментарий от Weres

Вот именно, у HTC запущено куча левых сервисов, которые не дают памяти для приложения ТС.
Под ведро не пилил, но не думаю что там как-то всё иначе.

ii8_ ★★★★
()

Кода не читал, но я надеюсь ты помнишь, что ресурсы Bitmap не освобождаются Garbate Collector'ом никогда, и тебе нужно вручную звать recycle() на каждую картинку, чтобы было место под новую картинку.

Почитай что-нибудь типа http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-l..., на SO килотонны похожих вопросов (н-р я не вижу у тебя purgable и sharable в options, и откуда вообще берется inSampleSize?)

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от ii8_

То есть на практике не встречались. Приложение, с которым работает пользователь, имеет наибольший приоритет, система закроет сервисы и заберёт ресурсы у всех фоновых процессов, чтобы отдать их активному.

Weres ★★★
()
Ответ на: комментарий от Int64

Пожалуйста. На четвертых андроидах битмапы со стандартным цветовым профилем текут. Сборщик мусора их не собирает и всё кончается OutOfMemory. Я, однажды, сталкивался с точно такой же проблемой: приложение грузило много изображений динамически, работало под 5-ым андроидом на нексусе, но невероятно быстро выжирало всю память и падало на старых и слабых девайсах. Профилировщик показывал, что память забита byte массивами входящими в состав Bitmap объектов. Ответ, помнится, где-то на StackOwerflow находил.

Weres ★★★
()
Ответ на: комментарий от Int64

Выкладывайте код, может кто поймет где утечка. Посмотрите профилировщиком, какие объекты теперь висят в памяти.

Weres ★★★
()
Ответ на: UpdateCreateTaskController.java от Int64

Я глянул по быстрому, обратите внимание, что BitmapFactory.deoceStream тоже принимает BitmapFactory.Options: http://developer.android.com/intl/ru/reference/android/graphics/BitmapFactory...

Используется, как минимум здесь. Вообще, там где идет работа с битмапами обязательно указывайте Options, иначе потечёт. Я поэтому создание опций в статический метод в утилиты и вынес, чтобы быстро подставлять везде, где только можно.

Weres ★★★
()
Ответ на: комментарий от Weres

Приложение, с которым работает пользователь, имеет наибольший приоритет.

и нет сервисов поприоритетнее пользовательского? я про это.
Но не спорю, что там проблема конкретно в прилаге ТС, которая не верно работает с ресурсами)

ii8_ ★★★★
()
Последнее исправление: ii8_ (всего исправлений: 1)
Ответ на: комментарий от Int64

попробуй подставить туда константу вместо твоей мега-функции. Например, 8. Чем меньше циферка, тем меньше памяти тратится (и течет, если она течет). Выстави options.inPurgeable, inInputShareable. Про GC я так и не понял, баг это или фича, но это просто факт - на старых андроидах без ручного освобождения начинается трындец почти сразу

олсо, если у тебя в телефоне включается-выключается 3d ускорение интерфейса (было в старых андроидах), попробуй выключить. Во времена второй версии включение ускорения могло привести вообще к любым последствиям

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 3)
Ответ на: комментарий от stevejobs

Знать бы за ранее что нужно освобождать память :D Я думал Java за тем и был придуман, чтобы память не текла.

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

Java затем и придумана, но проблема в том, что на андроиде не джава, а далвик. К «настоящей джаве» не имеет почти никакого отношения кромие формы фигурных скобочек :)

олсо, работа со внешними ресурсами (типа картинок, или например треды) написана как native на C++, джава как стандарт ничего тут сделать не может, могут пряморукие написатели нативной части далвика

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

Ну Apple сделал замену Objective C на нормальный Swift, почему Google не могу заменить Java на Go интересно.

Int64 ★★★
() автор топика
Ответ на: комментарий от stevejobs

Все картинки в layout'ах какие были почти с опциями стал грузить. Вроде перестало вылетать. А если у меня фоны часто используются, могу ли я просто создать статическую переменную Bitmap bg; и просто нужным ImageView присваивать этот фон, или так делать не стоит? может при вызове setImageBitmap он создает еще один Bitmap и тогда будет в 2 раза больше памяти кушать.

Int64 ★★★
() автор топика
Ответ на: комментарий от stevejobs

Еще как оказалось использовать Bitmap.createScaledBitmap лучше не использовать, качество низкое, и почему-то с OutOfMemory вылетает, вместо этого BitmapFactory использую с опциями.

Int64 ★★★
() автор топика
Ответ на: комментарий от stevejobs

Походу можно так, потому-что когда я удаляю Bitmap, то ImageView становится черным )

Int64 ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.