2013-06-22 14 views
5

Stavo ricevendo OutOfMemoryError messaggi in LogCat e la mia app si bloccava perché gli errori non erano stati rilevati.

Due cose causavano il OutOfMemoryError:
1. Lettura di un file di testo di grandi dimensioni in una stringa.
2. Invio di quella stringa al mio TextView.

Semplicemente aggiungendo un fermo a queste due cose, non solo si cattura lo OutOfMemoryError ma sembra che risolva completamente il problema di esaurimento della memoria.
Niente più crash e niente più messaggi di errore in LogCat. L'app funziona perfettamente.

Com'è possibile? Cosa sta succedendo esattamente?


'Catching' OutOfMemoryError risolve completamente i problemi di memoria esaurita?

Con questo codice, mi è stato sempre il messaggi di errore & app crash:

try 
{ 
myString = new Scanner(new File(myFilePath)).useDelimiter("\\A").next(); 
} 
catch (FileNotFoundException e) 
{ 
e.printStackTrace(); 
} 


myTextView.setText(myString); 



Solo per 'catturare' il OutOfMemoryError, non più messaggi di errore in LogCat e nessun crash:

try 
{ 
myString = new Scanner(new File(myFilePath)).useDelimiter("\\A").next(); 
} 
catch (FileNotFoundException e) 
{ 
e.printStackTrace(); 
} 
catch(OutOfMemoryError e) 
{ 
} 


try 
{ 
myTextView.setText(myString); 
} 
catch(OutOfMemoryError e) 
{ 
} 
+2

per vedere i registri aggiungere e.printstacktrace in OutOfMemoryError blocco catch – Calvin

+1

d'accordo con @Droider. Non vedi i messaggi di errore perché non li stai stampando come prima. – csmckelvey

+0

Vedere http://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror – Raedwald

risposta

1

Se si cattura l'OutOfMemoryError, il garbage collector tenta di liberare la memoria utilizzata in precedenza e, quindi, l'applicazione può continuare se l'applicazione farà si che il Garbage Collector fa il suo lavoro (es l'applicazione non ha più un riferimento a quella tua grande stringa).

Tuttavia, la cattura di un errore OutOfMemoryError è tutt'altro che infallibile. Vedi Catching java.lang.OutOfMemoryError?.

2

Immagino che la tua stringa non sia caricata completamente, o anche se lo è (potrebbe lanciare l'errore subito dopo aver aggiunto il testo), ciò che accade dipende dalla memoria corrente disponibile per la tua app quindi catturare OutOfMemoryError non è un soluzione praticabile qui.

Se si desidera caricare un file di stringa di grandi dimensioni e visualizzarlo in un EditText, si consiglia di caricare solo una piccola parte del file (diciamo 50kB) e implementare un tipo di paging, ad esempio un pulsante che carica i prossimi 50kB. È anche possibile caricare linee aggiuntive mentre l'utente scorre attraverso lo EditText.

1

Quando si rileva l'eccezione, la JVM tenta di ripristinarla chiamando il Garbage Collector e raschiando gli oggetti che non vengono più utilizzati.

Questo potrebbe risolvere il problema nel tuo caso. Ma immagina che il problema appaia a causa di una cattiva codifica e perdite di memoria in tutto il codice. La cattura non risolverà il problema perché GC non raccoglierà alcun oggetto. GC eseguirà il kick-in più frequentemente e le prestazioni della tua applicazione diminuiranno fino a diventare inutilizzabili.

Fondamentalmente, questo errore si verifica quando la JVM non può allocare più memoria su heap per i nuovi oggetti.Catturare l'eccezione e lasciare che il GC ripulisca e rilasciare memoria potrebbe essere una soluzione, ma non sei mai assolutamente sicuro di essere in uno stato recuperabile. Vorrei utilizzare il blocco catch per recuperare dall'errore, registrarlo e chiudere l'applicazione. Se si vuole risolvere il problema della memoria in questo caso, farlo correttamente e inizializzare la JVM con più memoria (utilizzando l'argomento java -Xmx)

+0

Sto avendo l'eccezione in un metodo di riflessione dell'immagine. Posso rilevare l'errore se succede, interrompere l'elaborazione, pulire gli oggetti e usare semplicemente l'immagine originale? – frostymarvelous

+0

È davvero considerata una cattiva pratica catturare un'eccezione del genere. Una pratica migliore sarebbe quella di evitare che quell'eccezione si verifichi 1) cercando di scoprire dove il codice perde, 2) aumentando la memoria data alla JVM all'avvio del programma (con -Xmx). Inoltre, non sono sicuro di cosa intendi per "metodo di riflessione dell'immagine", puoi spiegarlo un po '? – darijan

+0

Fondamentalmente, creo una nuova immagine da una esistente che riflette l'immagine. Scusate, immagino che si presenti come Reflection. Ad ogni modo, il codice non perde. Ottengo l'errore qualche volta quando creo una nuova immagine con Bitmap.createBitmap. Se tutto fallisce, dovrò usare il sottocampionamento, credo, ma le immagini sono già abbastanza piccole. – frostymarvelous