Ho un'eccezione OutOfMemory con una galleria su 600x800 pixel JPEG.Android: OutofMemoryError: la dimensione della bitmap supera il budget della macchina virtuale senza motivo Posso vedere
L'ambiente
Sto usando Galleria con immagini JPG intorno 600x800 pixel.
Poiché il mio contenuto potrebbe essere un po 'più complesso delle semplici immagini, ho impostato ogni vista come un RelativeLayout che avvolge ImageView con il JPG.
Al fine di "accelerare" l'esperienza utente, ho una cache semplice di 4 slot che prefetta (in un looper) circa 1 immagine a sinistra e 1 immagine a destra sull'immagine visualizzata e le mantiene in una slot HashMap a 4 slot.
La piattaforma
Sto usando AVD di 256 MB di RAM e 128 Dimensione heap, con uno schermo 600x800. Si verifica anche su un target di Entourage Edge, tranne per il fatto che con il dispositivo è più difficile eseguire il debug.
Il problema
Sono stato sempre un'eccezione:
OutofMemoryError: bitmap size exceeds VM budget
E succede quando va a prendere la quinta immagine. Ho provato a cambiare la dimensione della mia cache di immagini, ed è sempre la stessa.
La cosa strana: Non ci dovrebbe essere un problema di memoria
Al fine di assicurarsi che il limite di heap è molto lontano da quello che mi serve, ho definito un array di 8MB manichino nella all'inizio, e lasciato senza riferimento, quindi viene immediatamente inviato. È un membro del filo attività ed è definito come segue
static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }
Il risultato è che la dimensione heap è quasi 11MB ed è tutto gratuito. Nota Ho aggiunto quel trucco dopo che ha iniziato a bloccarsi. Rende OutOfMemory meno frequente.
Ora sto utilizzando DDMS. Poco prima dello schianto (non cambia molto dopo l'incidente), DDMS mostra:
ID Heap Size Allocated Free %Used #Objects
1 11.195 MB 2.428 MB 8.767 MB 21.69% 47,156
E nella tabella di dettaglio mostra:
Type Count Total Size Smallest Largest Median Average
free 1,536 8.739MB 16B 7.750MB 24B 5.825KB
Il blocco più grande è 7.7MB. Eppure il LogCat dice:
ERROR/dalvikvm-heap(1923): 925200-byte external allocation too large for this process.
Se vi occupate la relazione tra la mediana e la media, è plausibile supporre che la maggior parte dei blocchi disponibili sono molto piccole. Tuttavia, c'è un blocco abbastanza grande per la bitmap, è 7.7M. Come mai non è ancora abbastanza?
Nota: ho registrato una traccia heap. Osservando la quantità di dati allocati, non sembra che siano allocati più di 2M. Corrisponde al rapporto di memoria gratuito di DDMS.
- Potrebbe essere che provo qualche problema come heap-frammentazione?
- Come posso risolvere/risolvere il problema?
- L'heap è condiviso con tutti i thread?
- Potrebbe essere che io interpreti la lettura DDMS in modo errato e non ci sia davvero nessun blocco 900K da allocare? Se è così, qualcuno può dirmi dove posso vederlo?
Grazie mille
Meymann
È possibile ottenere alcuni morsi qui se si pubblica il codice che in realtà preleva/decodifica/memorizza nella cache/in scadenza le bitmap. Il problema è quasi certamente quello che stai facendo lì, non qualcosa che richiede di scavare nell'interno dell'allocazione dell'heap. –
Durante il debug del codice, il mio principale sospetto è sempre il mio codice. Per eseguire il debug, ottengo suggerimenti dall'ambiente. Sfortunatamente, in questo caso: A. la creazione di un codice semplice che legge 3 immagini di 600x800 alla volta in una cache produrrebbe risultati simili sporadicamente (verificati, per fare in modo che accada più rapidamente, si possono aggiungere matrici non referenziate), B. Uso gli strumenti per sondare il problema, ma i suggerimenti che ottengo dagli strumenti non coincidono. C. Il punto di questa domanda è ottenere suggerimenti su ciò che è buona pratica, cosa c'è di sbagliato con le mie conclusioni sulla lettura DDMS, e se c'è una soluzione alternativa. – Meymann
** Un modo molto semplice per riprodurre il problema in un altro modulo ** 1. nella classe Attività, aggiungere static {byte dummy [] = new byte [4096]; } per forzare l'espansione dell'heap (e rimuovere i dubbi). 2. creare un ViewFlipper. 3. Aggiungere circa 10 ImageView in cui ciascuno si riferisce a un drawable bitmap 600x800. 4. Quando si blocca, guarda il DDMS. – Meymann