2014-10-13 33 views
6

Durante il ridimensionamento di bitmap di grandi dimensioni per il caricamento di immagini più veloce su un server, occasionalmente ho eseguito l'accesso a OutOfMemoryErrors. Per evitare ciò calcolo la quantità di memoria necessaria e controllo se supera Runtime.getRuntime(). MaxMemory() prima di provare a ridimensionare un'immagine.Heap non espandibile sull'emulatore Genymotion

Tuttavia, si verificano ancora errori OOM anche se l'immagine si adatta facilmente all'heap.

Il dispositivo emulato (Galaxy SII API 16) mi dà una memoria massima di 67108864 byte utilizzando il metodo precedente.

Nel seguente frammento, la dimensione heap è 43975 K e solo 15 K di quella memoria è in uso. Per la mia allocazione di ~ 31K, l'heap dovrebbe crescere automaticamente a circa 45K, che non è ancora vicino alla dimensione massima di 64 MiB. Ma come si può vedere, invece di espandere l'heap, dalvik vm esaurisce la memoria.

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. 

Mi chiedo se questo può accadere su un dispositivo reale o anche se questo potrebbe essere un bug genymotion.

L'heap è garantito per l'espansione fino a maxMemory()? JavaDoc per Runtime.getRuntime(). FreeMemory() dice che "può" espandersi, qualunque cosa significhi.

Ho solo bisogno di un modo realiable per calcolare la quantità di memoria che posso usare, questo è come ho fatto, per favore correggetemi se sbaglio:

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

Questa chiamata fa sì che l'OutOfMemoryError:

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

Hai risolto questo problema? – KinGPinG

+0

Purtroppo no. Qualche idea? – wkarl

+0

No, mi dispiace mi sto ancora occupando di esso. Ti farò sapere se trovo qualcosa di utile. – KinGPinG

risposta

5

Out of memory on a 31961100-byte allocation

La bitmap è 32M. VM non può allocare spazio lineare 32M per memorizzare bitmap. L'heap è frammentato, quindi anche se il tuo heap ha 32M di spazio libero non è sempre possibile allocare lo spazio lineare. Puoi provare a liberare più memoria possibile e chiamare GC prima di decodificare il flusso.

Provare a decodificare la bitmap in più effective way. Or process image in parts. Se ci dici perché hai bisogno di questa immagine, possiamo dirti come gestirla.

+0

Sto già decodificando la bitmap con un inSampleSize> 1. L'elaborazione dell'immagine in parti probabilmente non è nemmeno un'opzione - anche se potessi salvarla in parti mi aspetterei che ci fossero artefatti quando la ricolleghiamo (corretto me se sbaglio). Quello che faccio attualmente è ridimensionare l'immagine fino a una lunghezza laterale massima di 1920 px prima di caricarla su un server. – wkarl

+0

C'è un modo per trovare lo spazio contiguo massimo disponibile per le allocazioni? – wkarl

+2

No. Controlla questa risposta: http://stackoverflow.com/questions/3331527/android-resize-a-large-bitmap-file-to-scaled-output-file Puoi anche creare un processo separato per ridimensionare l'immagine lì, sarà hanno le stesse dimensioni di heap solo per l'elaborazione delle immagini. Prova ad abilitare l'opzione userLargeHeap in manifest. Oppure carica l'immagine originale usando i flussi e ridimensionala sul lato server. – Leonidos

1

Hai un mucchio di 42MB, di cui 14MB è già utilizzato, il 67% (28M) è libero/a disposizione

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. 

Si sta tentando di allocare ~ 31M (non 31K), che è maggiore di 28M che è disponibile, risultando in OOM.

Per i dettagli su come interpretare dalvikvm memory allocation log message take a look at debugging memory

C'è molto di utilizzo della memoria condivisa succedendo in Android, per calcolare correttamente per l'utilizzo della memoria processo refer this SO question

Android best practices on efficient bitmap memory management può essere di aiuto

+0

42MB è la dimensione corrente dell'heap, Runtime.getRuntime(). MaxMemory() mi dà 64 megabyte però. Avevo l'impressione che potessi usare fino a 64 megabyte e che l'heap si espandesse fino a quella dimensione. Il post di StackOverflow è interessante ma in realtà non risponde alla domanda su come calcolare in modo affidabile la quantità di memoria che posso allocare in modo sicuro. – wkarl

1

Una cosa che si potrebbe provare a modificare è il file build.props della ROM.

Su Genymotion emulatore si può provare a eseguire la seguente via shell di root:

cat /system/build.prop | grep dalvik 

e sarebbe visualizzare la riga con le impostazioni Dalvik:

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

E maxmemory viene anche segnalato come 268435456 byte sull'emulatore che ho sperimentato.

Quindi, si può provare a giocare con questa impostazione. Inoltre, assicurarsi che la memoria allocata nelle impostazioni di VirtualBox sia compatibile con questi valori.

+1

In realtà non sono preoccupato per l'emulatore. Mi stavo chiedendo se la stessa cosa potrebbe accadere ai dispositivi degli utenti reali là fuori che sarebbe male. – wkarl