2012-12-17 5 views
11

Ho un'applicazione Android che registra JSONObject come entità utilizzando l'oggetto ByteArrayEntity. Ecco come sembra:HttpClient.execute throw OutOfMemoryError

post.setEntity(new ByteArrayEntity(entity.getBytes("UTF-8"))); 
result = client.execute(post, handler); 

entità è una String. Il gestore è ResponseHandler<String> e il client è un HttpClient. Funziona bene con l'emulatore e su alcuni dispositivi. Ma, a volte sto ottenendo OutOfMemoryError mentre eseguo su x10i (noto anche come XPERIA).

Qui è stack:

java.lang.OutOfMemoryError 
at org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:79) 
at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:93) 
at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83) 
at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170) 
at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106) 
at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129) 
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:171) 
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:580) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:678) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:652) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) 
at com.test.application.api.Request.post(Request.java:102) 
at com.test.application.api.API.getResult(API.java:123) 
at com.test.application.api.APITask.doInBackground(APITask.java:127) 
at com.test.application.api.APITask.doInBackground(APITask.java:1) 
at android.os.AsyncTask$2.call(AsyncTask.java:185) 
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
at java.lang.Thread.run(Thread.java:1019) 

Come ho detto, sto solo postando un JSONObject come String. Potrebbe essere al massimo 200 caratteri. Cosa c'è che non va?

+0

Qual è la dimensione della risposta dal server? –

+0

È circa 5-6kb. –

+2

Ci sono errori simili su http://stackoverflow.com/questions/3055614/out-of-memory-error-my-apps-fault, ma sembra essere correlato all'utilizzo generale della memoria, non isolato da AbstractSessionInputBuffer . –

risposta

5

I dispositivi Android hanno un limite di memoria per processo. L'impostazione predefinita predefinita è 24 MB, ma alcuni dispositivi hanno un valore inferiore, ad esempio 16 MB o forse inferiore. L'X10i sembra avere 384 MB di RAM, che è basso per un moderno dispositivo Android (1 GB è ora standard), e questo può porre ulteriori vincoli.

vorrei suggerire:

  1. Prima controllare il limite per processo sul dispositivo. Utilizzare ActivityManager.getMemoryClass() per verificare.
  2. Controllare l'utilizzo della memoria effettiva utilizzando DDMS.

Potreste scoprire che, appena prima di effettuare questa chiamata, siete già al limite superiore della memoria; l'inizializzazione di HTTPClient e la chiamata potrebbe portarti oltre il limite. Ciò sarà più probabile se si verifica l'OOM sulla prima chiamata .

Se ciò accade solo sporadicamente, o dopo un numero di chiamate, è possibile che si verifichi una perdita di memoria. Il DDMS ti aiuterà a rintracciare ciò usando la funzione get allocations.

+0

Grazie per i suggerimenti, cercherò di nuovo come hai indicato. –

1

In caso di java.lang.OutOfMemoryError è probabile che l'applicazione mantenga riferimenti a oggetti che dovrebbero essere liberati. Prova a eseguire il debug di questa applicazione su questo telefono, non in emulatore.

1

Sulla superficie, solo 200 byte allocati non molto spesso non eseguiranno il processo di memoria anche su Android. Quindi uno di questi presupposti è sbagliato. Molto probabilmente una delle seguenti condizioni è vera:

1) Nel caso di errore vengono allocati più di 200 byte (ad esempio, viene assegnato un nuovo HttpClient per ogni chiamata).

2) Questo codice viene sempre chiamato molto spesso

3) Esiste già un problema di memoria (come con le immagini) e questo è stato solo l'ultimo di allocazione che ha avuto l'applicazione oltre i suoi limiti.

Quante volte è stata questa linea di codice il colpevole di questo problema? Se la risposta è molti, allora 1) o 2) sembra probabile. Poiché non abbiamo il codice di tutte le app è difficile da diagnosticare, ma guardiamo all'evento/circostanza che innesca questo codice - viene richiamato da un tocco o da una mossa - e in tal caso ciò accade ogni millisecondo come utente trascina il dito sullo schermo perché non c'è sonno nel ciclo onTouch? Questo è il genere di cose che potrebbero variare da una piattaforma all'altra.

Se questa riga di codice ha causato il problema una o due volte, potrebbe essere il momento di cercare un problema generale di utilizzo della memoria. Cerca di determinare quanto vicino è il limite di memoria dell'applicazione. L'indennità varia con la versione di Android, quindi questo potrebbe essere un altro motivo per cui non lo vedi nell'emulatore. Prova a testare con la stessa versione di Android che sta riscontrando il problema.