2012-12-17 54 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版本进行测试。

相关问题