java.lang.OutOfMemoryError: размерът на растерното изображение надвишава бюджета на VM

Опитвам се да променя оформлението на моето приложение от портретно на пейзажно и обратно. Но ако го правя често или повече от веднъж, понякога приложението ми се срива. По-долу е регистърът на грешките. Моля, предложете какво може да се направи?

 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 oragnanalBitmap = mRetriever.getFrameAtTime(i, MediaMetadataRetriever.OPTION_NEXT_SYNC); }   -  person Dwivedi Ji    schedule 11.07.2012
comment
възможен дубликат на java.lang.OutOfMemoryError: размерът на растерната карта надвишава бюджета на VM - Android   -  person akshay    schedule 30.01.2014


Отговори (12)


Една от най-честите грешки, които открих при разработването на приложения за Android, е

java.lang.OutOfMemoryError: Размерът на растерното изображение превишава бюджета на VM

грешка. Открих тази грешка често при дейности, използващи много растерни изображения след промяна на ориентацията: дейността се унищожава, създава се отново и оформленията се „раздуват“ от XML, като се консумира VM паметта, налична за растерни изображения.

Растерните изображения на предишното оформление на дейността не са правилно освободени от събирача на боклук, защото имат кръстосани препратки към тяхната дейност. След много експерименти намерих доста добро решение за този проблем.

Първо задайте атрибута „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() на вашата дейност, извикайте метода unbindDrawables(), предавайки препратка към родителския изглед и след това направете 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
страхотен код... единственият бъг, който имах с това, е когато има adapterView в оформлението. Те причиняват UnsupportedOperationException на removeAllViews(), току-що добавиха try catch на този ред и всичко работи добре. - person Mario Lenci; 15.02.2012
comment
Как се справяте с фонови изображения, добавени с метода setTheme?? - person Maxrunner; 07.03.2012
comment
пак нямам късмет :( - person swiftBoy; 22.11.2012

Получих грешката java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget на няколко пъти

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 посочва, че не трябва да се опитвате да принудите GC, трябва да оставите Davlik да се справи сам. В най-добрия случай това крие причината за проблема ви с паметта и замества загуба на производителност на процесора. - person William; 16.10.2013
comment
@Rafiq, бихте ли обяснили кога да се извика тази функция clearAllResources()? - person zhaojing; 06.02.2015

Това е практичен отговор, което се опитах да избегна този проблем по време на изпълнение

Runtime.getRuntime().gc();

Обаждането на Garbage Collector е добра идея.

person Pervez Alam    schedule 02.12.2011

Добавете този ред код към файла на манифеста на Android в тага „приложение“: - 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

Откъде идва източникът на изображението? Имате ли 9MB изображение в папката с drawables?

Има много дискусии по проблемите с родното управление на паметта за растерни изображения на 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. IMO не е добра идея да се извиква 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? Ако е наистина голям и имате повече от няколко от тях, може просто да нямате достатъчно памет, за да ги заредите наведнъж.

Също така, ако това се задейства от ротацията, не забравяйте, че вашата активност е унищожена и пресъздадена, така че може да се наложи да внимавате със статичните препратки. Разгледайте тази публикация в блог на Google. Ще трябва да внимавате да поддържате статични препратки към неща във вашия код, което може да доведе до изтичане на информация

person satur9nine    schedule 06.01.2011

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

може да помогне на този сайт. И трябва да освободите всички справки.

person Maidul    schedule 03.05.2011