2012-12-17 53 views
11

我有一個Android應用程序,使用ByteArrayEntity對象將JSONObject作爲實體發佈。這裏的外觀如下:HttpClient.execute拋出OutOfMemoryError

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

實體是String。處理程序是ResponseHandler<String>,客戶端是HttpClient。這在仿真器和某些設備上運行良好。但是,有時我在x10i(也稱爲XPERIA)上執行時遇到OutOfMemoryError。

這裏是堆棧:

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) 

正如我所說的,我只是發佈一個JSONObject的字符串。最多可能是200個字符。怎麼了?

+0

服務器響應的大小是多少? –

+0

大約5-6kb。 –

+2

也有類似的錯誤,例如http://stackoverflow.com/questions/3055614/out-of-memory-error-my-apps-fault,但它似乎與一般的內存使用有關,不是孤立的AbstractSessionInputBuffer 。 –

回答

5

Android設備具有每進程內存限制。默認的默認值爲24MB,但有些設備的值較低,例如16MB或更低。 X10i似乎擁有384MB RAM,對於現代Android設備(現在是標配1GB)來說,這是很低的,這可能會帶來額外的限制。

我建議:

  1. 首先檢查您的設備上的每個進程限制。使用ActivityManager.getMemoryClass()進行檢查。
  2. 使用DDMS查看您的實際內存使用情況。

你可能會發現,你是在進行此調用之前,你已經在內存的上限; HTTPClient的初始化和調用可能會超出限制。如果OOM發生在第一個呼叫上,則這將更有可能。

如果這種情況偶爾發生,或者經過多次調用後,可能會發生內存泄漏。 DDMS將幫助您使用get allocations功能進行跟蹤。

+0

感謝您的建議,我會再次按照您的指示看。 –

1

java.lang.OutOfMemoryError的情況下,很可能您的應用程序會保留對應該釋放的對象的引用。嘗試在此手機上調試此應用程序,而不是仿真器。

1

表面上,即使在Android上,只有不常分配的200個字節也不會使內存溢出內存。因此,其中一個假設是錯誤的。最可能出現以下情況之一:

1)在故障情況下分配了200多個字節(例如,爲每個呼叫分配了一個新的HttpClient)。

2)此代碼獲取調用非常經常

3)已經有一個內存問題(就像圖片),這是隻是把應用程序過去極限的最後分配。

這行代碼有多少次是這個問題的罪魁禍首?如果答案很多,那麼1)或2)看起來很可能。由於我們沒有所有的應用程序代碼,因此很難診斷,但要查看觸發此代碼的事件/情況 - 是通過觸摸還是移動來調用 - 如果是這樣,每當用戶發生這種情況時都會發生這種情況因爲onTouch循環中沒有睡眠,所以將手指拖過屏幕?這是可能因平臺而異的事情。

如果這行代碼只導致了一次或兩次的問題,那麼可能是查找一般性內存使用問題的時候了。嘗試確定應用程序的內存限制程度。該補貼因Android版本而異,所以這可能是您在模擬器中看不到它的另一個原因。嘗試使用遇到問題的相同Android版本進行測試。

相關問題