11

JSONObjectオブジェクトを使用してエンティティとして投稿する Android アプリケーションがありByteArrayEntityます。これがどのように見えるか:

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

エンティティはString. ハンドラはResponseHandler<String>で、クライアントはHttpClient. これは、エミュレーターと一部のデバイスでうまく機能しています。ただし、実行中に OutOfMemoryError が発生することがありますx10i(XPERIA とも呼ばれます)。

ここにスタックがあります:

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 文字です。どうしたの?

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

表面的には、あまり頻繁に割り当てられない 200 バイトのみが、Android でもプロセスがメモリ不足になることはありません。したがって、これらの仮定の 1 つが間違っています。ほとんどの場合、次のいずれかが当てはまります。

1) 200 バイトを超える割り当てが失敗した場合 (たとえば、呼び出しごとに新しい HttpClient が割り当てられている場合)。

2) このコードは非常に頻繁に呼び出されています

3) 既にメモリの問題 (画像など) があり、これはアプリが限界を超えた最後の割り当てでした。

このコード行がこの問題の原因となったのは何回目でしょうか? 答えが多い場合は、1) または 2) の可能性が高くなります。アプリのコードがすべて揃っているわけではないため、診断するのは困難ですが、このコードをトリガーするイベント/状況を調べてください。タッチまたは移動によって呼び出されているかどうか。 onTouch ループにスリープがないため、画面上で指をドラッグしますか? これは、プラットフォームごとに異なる可能性がある種類のものです。

このコード行が原因で問題が 1 回か 2 回しか発生していない場合は、一般的なメモリ使用の問題を探す時期かもしれません。アプリケーションがメモリ制限にどれだけ近づいているかを判断してください。許容量は Android のバージョンによって異なるため、これがエミュレーターに表示されない別の理由である可能性があります。問題が発生している同じ Android バージョンでテストしてみてください。

于 2012-12-20T21:21:19.427 に答える