【问题标题】:HttpClient.execute throwing OutOfMemoryErrorHttpClient.execute 抛出 OutOfMemoryError
【发布时间】:2012-12-17 11:23:42
【问题描述】:

我有一个 Android 应用程序,它使用 ByteArrayEntity 对象将 JSONObject 作为实体发布。如下所示:

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 个字符。怎么了?

【问题讨论】:

  • 服务器响应的大小是多少?
  • 例如stackoverflow.com/questions/3055614/…也有类似的错误,但似乎与一般内存使用有关,而不是与AbstractSessionInputBuffer隔离。
  • 谢谢,已经检查了所有答案,并使用了 DDMS。但正如我所说,在模拟器上一切都很好。
  • @Ogulcan 在使用您的应用一段时间后(打开+关闭一些活动,发出许多网络请求),您的应用的内存使用情况是多少(转到设置-> 应用程序管理器)?
  • OOM 是在第一次调用 HTTPClient 代码时发生,还是在多次/多次调用后发生?

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


【解决方案1】:

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

我建议:

  1. 首先检查设备上的每个进程限制。使用ActivityManager.getMemoryClass()查看。
  2. 使用DDMS 查看您的实际内存使用情况。

您可能会发现,就在您进行此调用之前,您已经处于内存上限; HTTPClient 的初始化和调用可能会使您超出限制。如果 OOM 发生在 first 调用上,则更有可能发生这种情况。

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

【讨论】:

  • 感谢您的建议,我会按照您的指示再看一遍。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    从表面上看,即使在 Android 上,仅分配不经常分配的 200 个字节也不会导致进程内存不足。因此,这些假设之一是错误的。以下情况最有可能是正确的:

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

    2) 这段代码经常被调用非常

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      相关资源
      最近更新 更多