Что такое внешняя память Dalvik? Проблемы с распределением изображений / проблема WeakHashMap

Я пытаюсь написать кеш изображений. Я использую WeakHashMap, чтобы держать загруженные изображения и показывать их в списке ImageView. Однако через некоторое время я сталкиваюсь с:

02-17 15:13:00.416: D/dalvikvm(11766): GC_FOR_MALLOC freed 0K, 69% free 3447K/10823K, external 21870K/22699K, paused 16ms
02-17 15:13:00.455: D/dalvikvm(11766): GC_EXTERNAL_ALLOC freed <1K, 69% free 3447K/10823K, external 21870K/22699K, paused 25ms
02-17 15:13:00.463: E/dalvikvm-heap(11766): 116160-byte external allocation too large for this process.
02-17 15:13:00.490: E/GraphicsJNI(11766): VM won't let us allocate 116160 bytes

После чего я лечусь с ошибкой OutOfMemoryError.

Очевидно, у меня кончается "внешняя память", что бы это ни было. Доступно много кучи, но это не имеет значения. Похоже, что GC не может очистить эту "внешнюю память", хотя единственные ссылки, которые у меня есть, - это слабый хеш и imageViews в списке (который должен быть только одним экземпляром, повторно использованным)...

Может кто-нибудь помочь мне пролить свет на этот вопрос? Что это за внешняя память, из которой у меня заканчивается? Почему GC не очищает старые изображения?

Изменить: с тех пор я узнал, что заставило мою память не освобождаться: WeakHashmap выпускает записи, когда на KEYS больше нет ссылок, а не когда на VALUES нет ссылок. Мой главный вопрос все еще остается: что это за внешняя память?

2 ответа

Проблема в том, что вы пытаетесь выделить больше памяти, чем доступно. Даже если у вас есть 60% свободного места, если вы попытаетесь выделить что-то 61% размера кучи, вы получите ошибку нехватки памяти.

Я полагаю, что базовый Android имеет 16 МБ динамической памяти, которая используется для всех объектов программы, включая вашу хэш-карту, поэтому вам не нужно много памяти. Некоторые отдельные устройства с настроенным ПЗУ могут иметь больше места, но по умолчанию составляет 16 МБ. Это на самом деле закодировано в самом Android, особенно в файле frameworks/base/core/jni/AndroidRuntime.cpp:

AndroidRuntime::startVm()
...
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
//LOGI("Heap size: %s", heapsizeOptsBuf);
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);

Вы можете быть в состоянии использовать recycle() метод и некоторые другие методы, чтобы минимизировать объем памяти вашего приложения, но если вам нужно хранить более 16 МБ данных, то вам не повезло.

Другие вопросы по тегам