Android: java.ленг.OutOfMemoryError: не удалось выделить выделение 23970828 байтов с 2097152 свободными байтами и 2 МБ до OOM

Я хочу показать точечный фото ImageView С SD карты, которая уже хранится. После запуска моего приложения происходит сбой и получение OutOfMemoryError ошибка:

(java.ленг.OutOfMemoryError: не удалось выделить выделение 23970828 байтов с 2097152 свободными байтами и 2 МБ до OOM)

Я понятия не имею, или почему его из памяти. Я думаю, что мой размер изображения очень большой, поэтому я попытался изменить его.

Iterator<String> it = imageArray.iterator();
while (it.hasNext()) {
  Object element = it.next();
  String objElement = element.toString();
  Log.e("objElement ", " = " + objElement);
  final ImageView imageView = new ImageView (getContext());
  final ProgressBar pBar = new ProgressBar(getContext(), null, 
                                           android.R.attr.progressBarStyleSmall);
  imageView.setTag(it);
  pBar.setTag(it);

  imageView.setImageResource(R.drawable.img_placeholder);
  pBar.setVisibility(View.VISIBLE);

  if (objElement.endsWith(mp3_Pattern)) {
     Log.e("Mp3 ", " ends with ");
     pBar.setVisibility(View.GONE);
     imageView.setImageResource(R.drawable.audio_control);
  }
  if (objElement.endsWith(png_Pattern)) {
     Bitmap bitmap = BitmapFactory.decodeFile(objElement);
     int size = Math.min(bitmap.getWidth(), bitmap.getHeight());
     int x = (bitmap.getWidth() - size) / 2;
     int y = (bitmap.getHeight() - size) / 2;
     Bitmap bitmap_Resul = Bitmap.createBitmap(bitmap, x, y, size, size);
     Log.e("bitmap_Resul "," = "+ bitmap_Resul);

     if (bitmap_Resul != bitmap) {
        bitmap.recycle();
     }
     imageView.setImageBitmap(bitmap_Resul);
     Log.e("png_Pattern ", " ends with ");
     Log.e(" bitmap "," = " + bitmap);
  }

  holder.linearLayout.addView(imageView);
  holder.linearLayout.addView(pBar);

информация журнала cat:

08-27 14:11:15.307    1857-1857/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.tazeen.classnkk, PID: 1857
    java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM
            at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
            at android.graphics.Bitmap.nativeCreate(Native Method)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:812)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:789)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:709)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:634)
            at com.example.tazeen.classnkk.AllPosts_Page$MyListAdapter.getView(AllPosts_Page.java:357)
            at android.widget.AbsListView.obtainView(AbsListView.java:2347)
            at android.widget.ListView.makeAndAddView(ListView.java:1864)
            at android.widget.ListView.fillDown(ListView.java:698)
            at android.widget.ListView.fillFromTop(ListView.java:759)
            at android.widget.ListView.layoutChildren(ListView.java:1659)
            at android.widget.AbsListView.onLayout(AbsListView.java:2151)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2086)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1843)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

24 ответов


OutOfMemoryError является наиболее распространенной проблемой, возникшей в android, особенно при работе с растровыми изображениями. Эта ошибка возникает виртуальной машиной Java (JVM), когда объект не может быть выделен из-за нехватки места в памяти, а также сборщик мусора не может освободить некоторое пространство.

как упоминалось Алексеем, вы можете добавить ниже сущности в свой файл манифеста android:hardwareAccelerated="false" , android:largeHeap="true" это будет работать для некоторых окружающей среды.

<application
    android:allowBackup="true"
    android:hardwareAccelerated="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

вы должны определенно прочитайте некоторые концепции разработчиков андроидов, особенно здесь: Отображение Растровых Изображений Эффективно

прочитайте все 5 тем и перепишите код еще раз. Если он все еще не работает, мы будем рады видеть, что вы сделали неправильно с учебным материалом.

вот некоторые из возможных ответов для этих типов ошибок в SOF

Android: BitmapFactory.decodeStream () из памяти с файлом 400KB с 2MB свободным кучи

как решить java.ленг.OutOfMemoryError неприятности в Android

Android: java.ленг.Исключение OutOfMemoryError

java.ленг.Исключение OutOfMemoryError

решение для OutOfMemoryError: размер растрового изображения превышает бюджет VM

Edit: из комментариев @cjnash

для тех, у кого все еще были сбои после добавления этой строки, попробуйте вставить изображение в папку res/drawable-xhdpi/ вместо res/drawable/ и это может решить вашу проблему.


вы пытались добавить это в свой манифест в разделе приложения? android:largeHeap="true"?

такой

  <application
      android:name=".ParaseApplication"
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme"
      android:largeHeap="true" >

на самом деле вы можете добавить в свой манифест эти строки android:hardwareAccelerated="false" , android:largeHeap="true" он работает для некоторых ситуаций, но имейте в виду, что другая часть кода может спорить с этим.

<application
    android:allowBackup="true"
    android:hardwareAccelerated="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

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

Так что исправить было просто изменение размера изображения :)


Это должно работать

 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inSampleSize = 8;

 mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options);

изменение размера ваш образ до установки книги так:

Bitmap.createScaledBitmap(_yourImageBitmap, _size, _size, false);

где размер-фактический размер ImageView. Вы можете достичь размера путем измерения:

imageView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

и использовать в следующем размере imageView.getMeasuredWidth() и imageView.getMeasuredHeight() на scaling.


использовать Скользить Библиотека и переопределить размер до меньшего размера;

Glide.with(mContext).load(imgID).asBitmap().override(1080, 600).into(mImageView);

Я решил эту проблему, изменив размер изображения до меньшего размера. Я использую форму xamarin. уменьшение размера изображения PNG решило проблему.


Я получил ниже ошибки

"E/ art: выбрасывание OutOfMemoryError" не удалось выделить 47251468 байт выделение с 16777120 свободными байтами и 23MB до OOM"

после добавления android:largeHeap="true" на AndroidManifest.в XML затем я избавился от всех ошибок

<application
    android:allowBackup="true"
    android:icon="@mipmap/guruji"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:largeHeap="true"
    android:theme="@style/AppTheme">

Soluton попробуйте это в файле манифеста и используйте библиотеку Glide

compile ' com.на GitHub.bumptech.скольжение:скольжение:3.7.0'

    **Use Glide Library and Override size to less size;**

 if (!TextUtils.isEmpty(message.getPicture())) {
            Glide.with(mContext).load(message.getPicture())
                    .thumbnail(0.5f)
                    .crossFade()
                    .transform(new CircleTransform(mContext))
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(holder.imgProfile);
        } 

android: hardwareAccelerated="false"

android: largeHeap= "true"

<application
    android:allowBackup="true"
    android:hardwareAccelerated="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

использовать эту библиотеку

  compile 'com.github.bumptech.glide:glide:3.7.0'   

Его Рабочее Счастливое Кодирование

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;


public class CircleTransform extends BitmapTransformation {
    public CircleTransform(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;

        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;

        // TODO this could be acquired from the pool too
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}

проблема: не удалось выделить выделение 37748748 байтов с 16777120 бесплатные байты и 17MB до OOM

решение : 1.откройте файл манифеста 2. внутри тега приложения просто добавьте ниже двух строк

 android:hardwareAccelerated="false"
 android:largeHeap="true"

пример :

 <application
        android:allowBackup="true"
        android:hardwareAccelerated="false"
        android:largeHeap="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

У меня тоже проблема.

то же самое с большинством других выше. Проблема вызвана огромным имиджем.

просто измените размер некоторых изображений, и не нужно менять код.


Я новичок в разработке android, но я надеюсь, что мое решение поможет, оно отлично работает в моем состоянии. Im с помощью Imageview и установить его фон в "src", потому что я пытаюсь сделать анимацию кадра. Я получил ту же ошибку, но когда я попробовал этот код, он работал

int ImageID = this.Resources.GetIdentifier(questionPlay[index].Image.ToLower(), "anim", PackageName);
            imgView.SetImageResource(ImageID);
            AnimationDrawable animation = (AnimationDrawable)imgView.Drawable;
            animation.Start();
            animation.Dispose();

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


я столкнулся с этой проблемой, когда я не убил свою старую деятельность при переходе к новой деятельности. Я исправил это с finish();

    Intent goToMain = new Intent(this,MainActivity.class);
    startActivity(goToMain);
    finish();

Это сработало для меня: просто переместите изображения из папки drawable в drawable-hdpi.


Bitmap image =((BitmapDrawable)imageView1.getDrawable()).getBitmap();

ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,50/100,byteArrayOutputStream);

50/100 если используется 100, то оригинальное разрешение может остановить приложения из-за нехватки памяти.

Если 50 или менее 100 это будет 50% или менее 100 разрешение, так что это предотвратит из проблемы с памятью


Я обнаружил, что изображения в папке "drawable"будут преобразованы в гораздо большее изображение на телефонах с высоким разрешением. Например, изображение 200k будет повторно сопоставлено с более высоким разрешением, например 800k или 32000k. Я должен был обнаружить это самостоятельно и до сих пор не видел документацию для этой ловушки памяти кучи. Чтобы предотвратить это, я помещаю все в папку drawable-nodpi (в дополнение к использованию "опций" в BitmapFactory на основе конкретной кучи устройств). Я не могу позволить себе иметь размер моего приложения раздутые с несколькими выдвижными папками, особенно в связи с тем, что диапазон дефс экрана так обширен сейчас. Хитрость в том, что studio теперь специально не указывает папку "drawable-nodpi" как таковую в представлении проекта, она просто показывает папку "drawable". Если вы не будете осторожны, когда вы поместите изображение в эту папку в studio, оно фактически не будет сброшено в drawable-nodpi:

Careful here 'backgroundtest' did not actually go to drawable-nodpi and will 
be resampled higher, such as 4x or 16x of the original dimensions for high def screens.

enter image description here

обязательно щелкните вниз к папке nodpi в диалог, поскольку представление проекта не будет показывать Вам все рисоваемые папки отдельно, как раньше, поэтому не сразу будет видно, что он пошел не так. Студия воссоздала ванильный "drawable" в какой-то момент для меня после того, как я удалил его давно:

enter image description here


вы должны изменить размер объекта в drawable. Он слишком большой для android для отображения. например, если вы устанавливаете изображение, попробуйте изображение с меньшим количеством пикселей. Это работает на меня. Спасибо. :)


ваше приложение сбой, потому что ваш размер изображения (в Мб или КБ) слишком большие таким образом, он не выделяет пространство для этого. Поэтому перед вставкой изображения в drawable просто уменьшите размер.

или

вы можете добавить следующее В теге приложения в Манифесте.в XML

 android:hardwareAccelerated="false"
    android:largeHeap="true"
    android:allowBackup="true"

после добавления это приложение не будет сбой.

  • всегда используйте меньше размеров изображений в приложении.
  • если вы добавляете большие размеры изображений в приложении вы должны добавить выше syntex, но размер приложения будет увеличиваться.

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

Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
finalBitmap.compress(Bitmap.CompressFormat.JPEG,60,baos);
byte[] b = baos.toByteArray();

попробуйте самый простой. Возможно, ваше приложение сбой, потому что ваш размер изображения (в МБ) слишком велик, поэтому он не выделяет место для этого. Поэтому перед вставкой изображения в drawable просто уменьшите размер любым программным обеспечением просмотра или если вы берете изображение из галереи во время выполнения, чем перед его сохранением сжать растровое изображение. У меня получилось. наверняка для вас будет.


моя проблема решена после добавления

 dexOptions {
        incremental true
        javaMaxHeapSize "4g"
        preDexLibraries true
        dexInProcess = true
    }

в build.Gradle в файл


stream = activity.getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;

bitmap = BitmapFactory.decodeStream(stream, null, options);
int Height = bitmap.getHeight();
int Width = bitmap.getWidth();
enter code here
int newHeight = 1000;
float scaleFactor = ((float) newHeight) / Height;
float newWidth = Width * scaleFactor;

float scaleWidth = scaleFactor;
float scaleHeight = scaleFactor;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
resizedBitmap= Bitmap.createBitmap(bitmap, 0, 0,Width, Height, matrix, true);
bitmap.recycle();

затем в теге Appliaction добавьте largeheapsize= " true