HttpClient.execute抛出OutOfMemoryError

时间:2012-12-17 11:23:42

标签: java android json httpclient out-of-memory

我有一个Android应用程序,它使用JSONObject对象将ByteArrayEntity作为实体发布。这是它的样子:

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发布为String。它最多可能是200个字符。怎么了?

3 个答案:

答案 0 :(得分:5)

Android设备具有每进程内存限制。默认默认值为24MB,但某些设备的值较低,例如16MB或更低。 X10i似乎有384MB RAM,对于现代Android设备而言是低的(1GB现在是标准配置),这可能会产生额外的限制。

我建议:

  1. 首先检查设备上的每个进程限制。使用ActivityManager.getMemoryClass()进行检查。
  2. 使用DDMS查看实际的内存使用情况。
  3. 你可能会发现,在你打这个电话之前,你已经处于记忆的上限; HTTPClient的初始化和调用可能会超过限制。如果OOM发生在第一次调用上,则更有可能发生这种情况。

    如果只是偶尔发生这种情况,或者在多次调用之后,您可能会发生内存泄漏。 DDMS将使用get allocations功能帮助您追踪该功能。

答案 1 :(得分:1)

如果java.lang.OutOfMemoryError,您的应用程序可能会保留对应该被释放的对象的引用。尝试在这款手机上调试此应用程序,而不是在模拟器中调试。

答案 2 :(得分:1)

从表面上看,即使在Android上,只有200个不经常分配的字节也不会使进程无法运行。因此,其中一个假设是错误的。最有可能是下列之一:

1)在失败的情况下分配了超过200个字节(例如,为每个呼叫分配了一个新的HttpClient)。

2)此代码经常被称为非常

3)已经存在内存问题(如图片),这只是应用程序超出其限制的最后一次分配。

这行代码多少次是这个问题的罪魁祸首?如果答案很多,那么1)或2)看起来很可能。由于我们没有所有的应用程序代码,因此难以诊断,但是要查看触发此代码的事件/环境 - 是通过触摸还是移动来调用 - 如果是这样,那么每毫秒都会发生这种情况因为onTouch循环没有睡眠,所以在屏幕上拖动手指?这种情况可能因平台而异。

如果这行代码只导致问题一次或两次,那么可能是时候寻找一般内存使用问题了。尝试确定应用程序的内存限制有多接近。允许范围因Android版本而异,因此这可能是您在模拟器中看不到它的另一个原因。尝试使用遇到此问题的相同Android版本进行测试。