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

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

 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 

Ответы [ 12 ]

50 голосов
/ 21 июля 2011

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

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

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

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

Сначала установите атрибут «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. Удаляет дочерние элементы в каждой группе просмотра
12 голосов
/ 07 февраля 2012

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

1) При переключении из приложения и обратно в приложение через некоторое время (Нажмите кнопку «Домой» и после просмотра некоторыхurl)

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

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

Наконец-то я решил ошибку в следующемпуть

    public void clearAllResources() {

    // Set related variables null

    System.gc();
    Runtime.getRuntime().gc();
   }
8 голосов
/ 02 декабря 2011

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

Runtime.getRuntime().gc();

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

4 голосов
/ 27 января 2014

Добавьте эту строку кода в файл манифеста 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"
       >
3 голосов
/ 01 июня 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);
3 голосов
/ 16 мая 2012

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

try {

...

}
catch(OutOfMemoryError error)  {
    //decide what to do when there is not more memory available
}
3 голосов
/ 06 января 2011

Откуда берется источник изображения? У вас в папке drawables есть изображение размером 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 () каждый раз, когда я заканчиваю с растровым изображением, например ::10000

private void changeImage() {
     if (mCurrentImage != null) {
          mCurrentImage.recycle();
          mCurrentImage = null;
          System.gc();
     }
     mCurrentImage = getNewImage();
}
3 голосов
/ 06 января 2011

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

2 голосов
/ 30 марта 2013

Я сделал несколько дополнений к отличному ответу @ hp.android:

  1. Вместо определения идентификатора RootView в каждом классе 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);
             }
         }
     }
2 голосов
/ 06 января 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...