java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины

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

 01-06 09:52:27.787: ERROR/dalvikvm-heap(17473): 1550532-byte external allocation too large for this process. 01-06 09:52:27.787: ERROR/dalvikvm(17473): Out of memory: Heap Size=6471KB, Allocated=4075KB, Bitmap Size=9564KB 
 01-06 09:52:27.787: ERROR/(17473): VM won't let us allocate 1550532 bytes 
 01-06 09:52:27.798: DEBUG/skia(17473): --- decoder->decode returned false
 01-06 09:52:27.798: DEBUG/AndroidRuntime(17473): Shutting down VM
 01-06 09:52:27.798: WARN/dalvikvm(17473): threadid=3: thread exiting with uncaught exception (group=0x4001e390)
 01-06 09:52:27.807: ERROR/AndroidRuntime(17473): Uncaught handler: thread main exiting due to uncaught exception
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473): java.lang.RuntimeException: Unable to start activity ComponentInfo{}: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3812) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread.access$2300(ActivityThread.java:126) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1936) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.os.Handler.dispatchMessage(Handler.java:99) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.os.Looper.loop(Looper.java:123) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread.main(ActivityThread.java:4595) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at java.lang.reflect.Method.invokeNative(Native Method)
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at java.lang.reflect.Method.invoke(Method.java:521) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at dalvik.system.NativeStart.main(Native Method)
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.LayoutInflater.createView(LayoutInflater.java:513) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.LayoutInflater.inflate(LayoutInflater.java:385) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.LayoutInflater.inflate(LayoutInflater.java:320) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.LayoutInflater.inflate(LayoutInflater.java:276) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.Activity.setContentView(Activity.java:1629) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at onCreate(Game.java:98)
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     ...  12 more
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473): Caused by: java.lang.reflect.InvocationTargetException 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.widget.LinearLayout.<init>(LinearLayout.java:92) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at java.lang.reflect.Constructor.constructNative(Native Method)
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at java.lang.reflect.Constructor.newInstance(Constructor.java:446) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.LayoutInflater.createView(LayoutInflater.java:500) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     ...  22 more
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:464) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:340) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.content.res.Resources.loadDrawable(Resources.java:1705) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.content.res.TypedArray.getDrawable(TypedArray.java:548) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.View.<init>(View.java:1850) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.View.<init>(View.java:1799) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     at android.view.ViewGroup.<init>(ViewGroup.java:296) 
 01-06 09:52:27.857: ERROR/AndroidRuntime(17473):     ...  26 more 

person Angel    schedule 06.01.2011    source источник
comment
в следующий раз используйте кнопку кода формата, а не кнопку цитаты блока. кнопка цитаты портит сообщение   -  person J-16 SDiZ    schedule 06.01.2011
comment
Я тоже получаю эту ошибку, но решения нет. Я получаю эту ошибку, когда пытаюсь получить кадр видеофайла из класса MetaDataRetriver, My Code MediaMetadataRetriever mRetriever = new MediaMetadataRetriever (); mRetriever.setDataSource (this.videoPath); for (int i = 0; i ‹TimeUnit.MILLISECONDS .toMicros (listVideoFileDuration.get (k)); i = i + 5000000) {Bitmap oragnalBitmap = mRetriever.getFrameAtTime (i, MediaMetadataRetriever.OPTION_NEXT_SYNC); }   -  person Dwivedi Ji    schedule 11.07.2012


Ответы (12)


Одна из самых распространенных ошибок, которые я обнаружил при разработке приложений для Android, - это

java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины

ошибка. Я часто обнаруживал эту ошибку в Activity с использованием большого количества растровых изображений после изменения ориентации: Activity уничтожается, создается снова, а макеты «раздуваются» из XML, потребляя память виртуальной машины, доступную для растровых изображений.

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

Сначала установите атрибут «id» в родительском представлении вашего XML-макета:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/RootView">
        ...

Затем в методе onDestroy() вашего Activity вызовите метод unbindDrawables(), передав ссылку на родительский View, а затем выполните System.gc().

    @Override
    protected void onDestroy() {
        super.onDestroy();

        unbindDrawables(findViewById(R.id.RootView));
        System.gc();
    }

    private void unbindDrawables(View view) {
        if (view.getBackground() != null) {
            view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
            ((ViewGroup) view).removeAllViews();
        }
    }

Этот unbindDrawables() метод рекурсивно исследует дерево представлений и:

  1. Удаляет обратные вызовы для всех фоновых чертежей
  2. Удаляет дочерние элементы из каждой группы просмотра
person hp.android    schedule 21.07.2011
comment
это устранило проблему для моего случая ... всегда получалось исключение layoutinflate при раздутии большого макета с большим количеством графики ... спасибо! - person cV2; 24.08.2011
comment
отличный код ... единственная ошибка, с которой я столкнулся, - это когда в макете есть адаптерView. Они вызывают исключение UnsupportedOperationException в removeAllViews (), просто добавили попытку уловить эту строку, и все сработало нормально. - person Mario Lenci; 15.02.2012
comment
Что делать с фоновыми изображениями, добавленными с помощью метода setTheme ?? - person Maxrunner; 07.03.2012
comment
все равно не повезло :( - person swiftBoy; 22.11.2012

У меня была ошибка java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины в несколько раз

1) При переключении из приложения и обратно в приложение через некоторое время (нажмите кнопку домой и после просмотра URL-адреса)

2) При частом входе / выходе из приложения (в течение 10 секунд)

3) При переключении устройства по горизонтали / вертикали

Наконец, я решил ошибку следующим образом

    public void clearAllResources() {

    // Set related variables null

    System.gc();
    Runtime.getRuntime().gc();
   }
person Rafiq    schedule 07.02.2012
comment
Поскольку в документации по производительности Android указано, что вы не должны пытаться принудительно использовать сборщик мусора, вы должны позволить Davlik справиться с этим самостоятельно. В лучшем случае это скрывает причину вашей проблемы с памятью и заменяет потерю производительности процессора. - person William; 16.10.2013
comment
@Rafiq, не могли бы вы объяснить, когда вызывать эту функцию clearAllResources ()? - person zhaojing; 06.02.2015

Это практический ответ, что я пытался избежать этой проблемы во время выполнения

Runtime.getRuntime().gc();

Вызов сборщика мусора - хорошая идея.

person Pervez Alam    schedule 02.12.2011

Добавьте эту строку кода в файл манифеста Android внутри тега «application»: - android: largeHeap = «true»

<application
         android:theme="@android:style/Theme.NoTitleBar"
        android:allowBackup="true"
        android:largeHeap="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
       >
person Community    schedule 27.01.2014

У вас утечка ресурсов (скорее всего, объект Drawable). Попробуйте инструменты в Какие инструменты и методы Android лучше всего подходят для поиска утечек памяти / ресурсов?

person J-16 SDiZ    schedule 06.01.2011

Откуда берется источник изображения? У вас есть изображение размером 9 МБ в папке с чертежами?

Есть много дискуссий по проблемам с собственным управлением памятью растровых изображений Android, например. http://code.google.com/p/android/issues/detail?id=10821, http://code.google.com/p/android/issues/detail?id=8488, http://groups.google.com/group/android-developers/browse_thread/thread/ed57849ef705d421/11af8362d77a8cf4?lnk=raot. Мне повезло с явным вызовом recycle () и System.gc () каждый раз, когда я заканчиваю работу с растровым изображением, например:

private void changeImage() {
     if (mCurrentImage != null) {
          mCurrentImage.recycle();
          mCurrentImage = null;
          System.gc();
     }
     mCurrentImage = getNewImage();
}
person Daren Robbins    schedule 06.01.2011

Сначала остановите свое приложение от сбоя во время выполнения, перехватив ошибку OutOfMemory в месте, которое, по вашему мнению, может вызвать эту ошибку, как показано ниже:

try {

...

}
catch(OutOfMemoryError error)  {
    //decide what to do when there is not more memory available
}
person Khawar Raza    schedule 16.05.2012

Вы можете решить проблему с помощью opts.inSampleSize=2; or opts.inSampleSize=4

BitmapFactory.Options opts = new BitmapFactory.Options();
// opts.inJustDecodeBounds = true; 
opts.inSampleSize=2;    
Bitmap myBitmap = BitmapFactory.decodeFile(st_imagepath,opts);
person W00di    schedule 01.06.2012

Ангел, аналогичная проблема опубликована в StackOverflow здесь @ Исключение OutOfMemory при загрузке растрового изображения из внешнего хранилища

И отсюда я сделал вывод, что SoftReference также может быть альтернативой для решения. Проверьте сообщение, это может оказаться полезным.

person Saurabh    schedule 06.01.2011

Я сделал несколько расширений для отличного ответа @hp.android:

  1. Вместо определения идентификатора RootView ID в каждом классе XML я динамически нахожу корневое представление с помощью android.R.id.content.
  2. Как говорит @Mario Lenci, AdapterView не поддерживает removeAllViews, поэтому я проверяю тип представления перед вызовом removeAllViews().
  3. ИМО, не рекомендуется вызывать System.gc() в каждом вызове onDestroy (например, этот ответ), поэтому я удалил тот.
  4. Я создал статический метод onDestroy, который вызываю из onDestroy во всех моих пользовательских классах Activity.
  5. Я добавил дополнительную защиту от ошибок и ведение журнала.

Вот код:

    public static void onDestroy(Activity activity) {
        View rootView = null;

        try {            
            rootView = ((ViewGroup) activity.findViewById(android.R.id.content))
                    .getChildAt(0);
        } catch (Exception e) {
            Log.w("Cannot find root view to call unbindDrawables on",
                  activity);
        }

        if (rootView != null) {
            Log.d("unbindDrawables", activity, rootView);
            unbindDrawables(rootView);
        }
    }

    /**
      * Utility method to unbind drawables when an activity is destroyed.  This
      * ensures the drawables can be garbage collected.
      */
     public static void unbindDrawables(View view) {
         if (view.getBackground() != null) {
             view.getBackground().setCallback(null);
         }

         if (view instanceof ViewGroup) {
             for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                 unbindDrawables(((ViewGroup) view).getChildAt(i));
             }

             try {                
                 // AdapterView objects do not support the removeAllViews method
                 if (!(view instanceof AdapterView)) {             
                     ((ViewGroup) view).removeAllViews();
                 }
             } catch (Exception e) {
                 Log.w("Ignore Exception in unbindDrawables", e);
             }
         }
     }
person Dan J    schedule 30.03.2013

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

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

person satur9nine    schedule 06.01.2011

http://yekmer.posterous.com/android-memory-management

может помочь этому сайту. И вы должны освободить все ссылки.

person Maidul    schedule 03.05.2011