2014-10-13 11 views
6

Podczas zmiany rozmiaru dużych bitmap dla szybszego przesyłania zdjęć na serwer, od czasu do czasu wpadałem na OutOfMemoryErrors. Aby temu zapobiec, obliczam wymaganą ilość pamięci i sprawdzam, czy przekracza skalowalność Runtime.getRuntime(). MaxMemory() przed próbą skalowania obrazu.Sterty nie rozwijały się na emulatorze Genymotion

Jednak nadal napotykam na błędy OOM, mimo że obraz powinien łatwo zmieścić się na stercie.

Emulowane urządzenie (Galaxy SII API 16) daje maksymalną pamięć 67108864 bajtów przy użyciu powyższej metody.

W poniższym fragmencie rozmiar sterty wynosi 43975 K i tylko < jest używane 15 000 MB tej pamięci. Przy mojej alokacji ~ 31K strop powinien rosnąć automatycznie do około 45K, który wciąż nie jest nawet zbliżony do maksymalnego rozmiaru 64 MiB. Ale jak widać, zamiast rozszerzania sterty, dalvik vm zabrakło pamięci.

10-13 20:35:57.223: D/dalvikvm(1201): GC_FOR_ALLOC freed 505K, 67% free 14692K/43975K, paused 31ms, total 31ms 
10-13 20:35:57.223: I/dalvikvm-heap(1201): Forcing collection of SoftReferences for 31961100-byte allocation 
10-13 20:35:57.251: D/dalvikvm(1201): GC_BEFORE_OOM freed 2K, 67% free 14689K/43975K, paused 29ms, total 29ms 
10-13 20:35:57.251: E/dalvikvm-heap(1201): Out of memory on a 31961100-byte allocation. 

Zastanawiam się, czy to może się zdarzyć na prawdziwym urządzeniu czy też może to być błąd genymotion.

Czy sterty gwarantowane rozszerzenie do maxMemory()? JavaDoc dla Runtime.getRuntime(). FreeMemory() mówi, że "może" rozwinąć, cokolwiek to znaczy.

Potrzebuję tylko realiable sposób obliczenia ilości pamięci można używać, to jest, jak to zrobiłem, proszę mnie poprawić, jeśli się mylę:

long maxMemory = Runtime.getRuntime().maxMemory(); 
long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
long availableMemory = maxMemory - usedMemory; 

To wywołanie powoduje OutOfMemoryError:

// outOptions has an appropriate inSampleSize 
BitmapFactory.decodeStream(inputStream, null, outOptions); 
+0

Czy rozwiązałeś ten problem? – KinGPinG

+0

Niestety nie. Jakieś pomysły? – wkarl

+0

Nie, przykro mi, wciąż mam z tym problemy. Dam ci znać, jeśli znajdę coś przydatnego. – KinGPinG

Odpowiedz

5

Out of memory on a 31961100-byte allocation

Twoja mapa bitowa to 32M. Maszyna wirtualna nie może przydzielić przestrzeni liniowej 32M do przechowywania bitmapy. Sterty są pofragmentowane, więc nawet jeśli sterty mają 32M wolnego miejsca, nie zawsze jest możliwe przydzielenie takiej przestrzeni liniowej. Możesz spróbować zwolnić jak najwięcej pamięci i wywołać GC przed dekodowaniem strumienia.

Spróbuj zdekodować swoją bitmapę w większej liczbie effective way. Or process image in parts. Jeśli powiesz nam, dlaczego potrzebujesz tego obrazu, możemy Ci powiedzieć, jak go obsłużyć.

+0

Już odszyfrowuję bitmapę za pomocą inSampleSize> 1. Przetwarzanie obrazu w częściach prawdopodobnie również nie jest opcją - nawet jeśli mógłbym zapisać je w częściach, spodziewałbym się, że artefakty zostaną zszyte razem (poprawne mnie, jeśli się mylę). Obecnie przeskalowuję obraz do maksymalnej długości boku 1920px przed przesłaniem go na serwer. – wkarl

+0

Czy istnieje sposób na znalezienie maksymalnej dostępnej przestrzeni dla alokacji? – wkarl

+2

Nie. Sprawdź tę odpowiedź: http://stackoverflow.com/questions/3331527/android-resize-a-large-bitmap-file-to-scaled-output-file Możesz również stworzyć oddzielny proces skalowania obrazu, mają taki sam rozmiar sterty tylko dla przetwarzania obrazu. Spróbuj włączyć opcję userLargeHeap w manifeście. Lub przesłać oryginalny obraz za pomocą strumieni i skalować go po stronie serwera. – Leonidos

1

masz kupę 42MB, z czego 14MB jest już używany, 67% (28M) jest wolny/dostępny

D/dalvikvm(1201): GC_BEFORE_OOM freed 2K, 67% free 14689K/43975K, paused ... 
    E/dalvikvm-heap(1201): Out of memory on a 31961100-byte allocation. 

Próbujesz przydzielić ~ 31M (nie 31 KB), który jest większy niż 28M, który jest dostępny, co daje OOM.

Aby uzyskać szczegółowe informacje na temat interpretacji dalvikvm memory allocation log message take a look at debugging memory

Istnieje wiele wykorzystanie pamięci dzielonej dzieje na Androida, aby prawidłowo obliczyć na proces zużycia pamięci refer this SO question

Android best practices on efficient bitmap memory management mogą być pomocne

+0

42 MB to bieżący rozmiar sterty, Runtime.getRuntime(). MaxMemory() daje 64 megabajtów. Miałem wrażenie, że mógłbym użyć do 64 megabajtów, a sterty rozszerzyłyby się do tego rozmiaru. Post Stackoverflow jest interesujący, ale tak naprawdę nie odpowiada na pytanie, w jaki sposób wiarygodnie obliczyć, ile pamięci mogę bezpiecznie przydzielić. – wkarl

1

jedna rzecz może spróbować zmodyfikować plik ROM.

Na Genymotion emulatora można spróbować wykonywania następujących czynności przez rootem:

cat /system/build.prop | grep dalvik 

i byłoby wyświetlić wiersz z ustawieniami Dalvik:

dalvik.vm.heapsize=256m 
dalvik.vm.lockprof.threshold=500 
dalvik.vm.stack-trace-file=/data/anr/traces.txt 

I maxmemory jest również zgłaszane jako 268435456 bajtów na emulatorze, z którym eksperymentowałem.

Możesz więc spróbować grać z tym ustawieniem. Należy również upewnić się, że pamięć przydzielona w ustawieniach VirtualBox jest zgodna z tymi wartościami.

+1

Naprawdę nie martwię się emulatorem. Zastanawiałem się tylko, czy to samo może się zdarzyć z rzeczywistymi urządzeniami użytkowników, które byłyby złe. – wkarl

Powiązane problemy