11

我有一个使用对象JSONObject作为实体发布的 Android 应用程序。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 作为字符串发布。最多可能是 200 个字符。怎么了?

4

3 回答 3

5

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

我会建议:

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

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

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

于 2012-12-21T10:04:48.397 回答
1

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

于 2012-12-20T19:31:44.003 回答
1

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

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

2) 这段代码经常被调用

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

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

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

于 2012-12-20T21:21:19.427 回答