2012-03-22 8 views
12

メモリエラーが発生しています。私はライブチャットアプリケーションに取り組んでいます。正常に動作していますが、デバイス上でアプリケーションを1〜2時間実行しているときに、ヒープサイズが増加していて、16 MBに達したときにアプリケーションがハングアップし、しばらくしてクラッシュして、結果のヒープサイズがout of memory due to heap size割り当てられた。ヒープサイズの増加によるアンドロイドのメモリ不足のエラー

私はHTC Explorerでアプリケーションをテストしています。私のアプリケーションでは、ほとんどのアクティビティでバックグラウンドスレッドが使用されていますが、Asnyc Taskを使用しています。

次のようなエラーが表示されます。

04-30 16:53:14.658: E/AndroidRuntime(5707): FATAL EXCEPTION: MagentoBackground 
04-30 16:53:14.658: E/AndroidRuntime(5707): java.lang.OutOfMemoryError: (Heap Size=20167KB, Allocated=16063KB, Bitmap Size=355KB) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.util.ByteArrayBuffer.<init>(ByteArrayBuffer.java:53) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:82) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:98) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:173) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
04-30 16:53:14.658: E/AndroidRuntime(5707):  at com.live2support.CustomHttpClient.executeHttpPost1(CustomHttpClient.java:163) 

ヒープサイズの制限はありますか。どうすれば問題を解決できますか?

+1

いくつかのコードを投稿してください。私の推測では、カスタムリスト内で大きなビットマップを使用しています。 – Venky

+0

...または大きな配列に? –

+0

私はapplication.iでビットマップを使用していません。drawableフォルダにいくつかの画像がありますが、それは私が持っている15から20枚もの画像ではありません。 – nikki

答えて

11

あなたの質問は2つの部分があります。

1)どのように私は私のテストデバイス上のヒープのサイズを決定することができますか?

2)私のアプリがヒープのサイズを超えているのはなぜですか?

質問1について、あなたは呼び出すことで、あなたのコード内で直接テストデバイス上のヒープのサイズを決定することができます

Runtime.getRuntime()maxMemory();。

詳細については、this postを参照してください。また、さまざまなデバイスで利用できるヒープサイズの例もあります。

また、ルートデバイスを実行している場合、インターフェイス経由でヒープサイズを直接設定(およびチェック)する方法があるかもしれません。たとえば、CyanogenModのさまざまなバージョンのAndroidでは、[設定]メニューから[CyanogenMod設定]、[パフォーマンス]、[VMヒープサイズ]の順に選択し、デバイスのヒープサイズを直接表示(および変更)できます。ヒープサイズを小さすぎるとデバイスが誤動作することがあります。

質問2について:あなたの特定の問題を診断するのに十分な情報を提供していない場合、そのような診断を行うことはできません。この問題を解決するための最善の策は、Androidで利用可能な非常に強力なメモリ解析ツール(一部はEclipse IDEに統合されているものもあります)に精通することです。私はEclipseからこれらのツールを使用していますので、以下で説明します。

まず、最新版のEclipse(インディゴなど)をインストールして、Eclipseのバージョンが最新であることを確認します。その後、

次に、Eclipseで、[ヘルプ/新規ソフトウェアをインストールし、上部にあるドロップダウンをクリックして、

"Indigo - http://download.eclipse.org/releases/indigo" 

次へ]を選択し、その隣にあるプラス記号をクリックすることにより、汎用ツール]カテゴリを開き、メモリアナライザとメモリアナライザ(チャート)を選択します(オプション)。これらのツールをインストールします。

次に、「ウィンドウ/環境設定」、「Android/DDMS」を選択し、HPROFアクションを「Eclipseで開く」として選択します。これにより、DDMSから生成されたHPROFヒープ・ダンプ・ファイルがEclipse用の適切な形式になり、EclipseのMemory Analyzer(上にインストールされたばかりです)で自動的にオープンされます。

これで、[ウィンドウ/開くパースペクティブ/その他/ DDMS]を選択してDDMSを開きます。左にあるデバイスアイコン(電話のように見える)を選択し、結果ウィンドウをドラッグすると、簡単に見える場所にドッキングすることができます。

デバイスがUSB経由でPCに接続され、アプリが動作していることを確認してください。

作成したデバイスタブで、実行中のアプリケーションのプロセスを選択します。漏れていることを知っているメモリが十分に占有されていても、クラッシュするほどではないほど、アプリケーションを実行してください。ここで、[デバイス]タブの[ダンプHPROFファイル]アイコンをクリックします。少し遅れて、ヒープに関するレポートを選択できるようになります。開始するには、Leak Suspects Reportをお試しください。このレポートはメモリ解析ツールで開きます。これは、あなたのアプリがメモリをどこで使用しているかを示します。さまざまな種類のオブジェクトをチェックし、必要と思われるデータの量に比べて膨大なものになっているかどうかを確認します。もしそうなら、それは漏れを示すかもしれない。

Hereは、DDMSとMemory Analyzer Toolを使用してヒープを生成して探索する方法を詳しく説明する素敵なチュートリアルです。

DDMS(またはEclipseのDDMSパースペクティブ)に戻ると、デバイスが接続されている間に[割り当てトラッカー]タブを選択し、デバイスタブからデバイスを選択し、そのデバイスのリストからアプリケーションのプロセスを選択できます。次に、[割り当てトラッカー]タブで[トラッキング開始]ボタンをクリックし、アプリケーションの関連操作(漏れていると思われる操作)を実行し、[割り振りの取得]ボタンをクリックして、[トラッキングを停止]ボタンを選択します。

これは、トラッキング中に発生したすべての割り当てを表示します(保存する量に制限があります)。これらのいずれかをクリックすると、割り当て時にスタックに移動し、そのスタックダンプのいずれかの部分をクリックすると、割り当てに関与したソースコードが表示されます。

これらのツールを使用すると、アプリのメモリリークを引き起こす可能性のあることを把握することができます。

+0

ありがとうございましたcurl .............. ....... – nikki

1

ヒープサイズの制限はデバイスによって異なります。 2.xデバイスでは、約20 MBまたは32 MBがあなたの限界だと思います。ヒープサイズの詳細については、Android heap size on different phones/devices and OS versionsを参照してください。

スタックトレースから、com.live2support.CustomHttpClient.executeHttpPost1()が問題の中心にあるように見えます。

+0

を入力してください。どうすればいいですか? – nikki

+0

通常のもの。私はこの順序で物事を試してみよう:1.コードの目視検査。また、他の人がチェックアウトできるように、あなたの関数をこの質問に追加してください。ソースレベルのデバッガを使用してコードをステップ実行します。 3. 2がトリックをしない場合は、DDMSを使用します。 http://developer.android.com/guide/developing/debugging/ddms.html – Sparky

7

これは古典的なメモリリークのようです。接続にはAsyncTaskを使用しています。 AsyncTaskを使用してコンテキストを適切に使用する方法がわからない場合、構成の変更(たとえば、デバイスのローテーション)に関してコンテキストをリークするのは非常に簡単です。

まず最初に - 私は強くあなたがこれを見てお勧めします:http://www.youtube.com/watch?v=_CruQY55HOk

あなたは、このようなメモリリークを持っている場合は、チェックお使いのデバイスを回転させると、ガベージコレクタがどのように動作するかを確認するには。回転するたびにLogCatにGC_... freed 211K, 71% free 300K/1024K, external 0K/0K, paused 1ms+1msのようなものがあるはずです。この部分の変更点を確認してください:300K/1024K。メモリリークがない場合、最初の部分は成長し、その後数GC後に小さくなるはずです。メモリリークが発生した場合、OOMエラーの点で、メモリリークが拡大して拡大します。

このようにメモリリークが発生していることを確認したら、MAT for Eclipseをインストールし、それを(前述のムービーと共に)使用する方法とその原因を確認します。

私の個人的な賭けは、AsyncTaskの悪い実装です - あなたはそれを破壊されたアクティビティから切り離して新しいものにアタッチしますか?そうでない場合は、CommonsWareの優れた例があります。AsyncTaskLoaderに切り替えると、AsyncTask(荷物を積み込むだけでなく)の代用としても大丈夫です。

+0

また、デバッガからアプリを起動したときにのみ表示されるOOMエラーに関する奇妙な問題がありました。ランチャーアイコンで正常に起動すると、メモリリークは発生しませんでした:http://stackoverflow.com/questions/10305037/leaking-memory-with-actionbarsherlock –

0

これはAndroid OSに従って2通りの方法で行うことができます。

  1. あなたは、より大きなヒープサイズを要求するには、Androidマニフェストのアプリケーションタグにandroid:largeHeap="true"を使用することができますが、これは任意の事前ハニカムデバイス上で動作しません。
  2. 2.3より前のデバイスでは、VMRuntimeクラスを使用できますが、これはGingerbread以上では機能しません。 HEAPSIZEは、あなたが他のアプリケーションやOSの機能には影響しません適切なサイズを入力していることを確認して設定する前に
VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE); 

。設定を行う前に、アプリがどれくらいの大きさをとっているかを確認してから、あなたの仕事を満たすためにサイズを設定してください。あまりメモリを使用しないと、他のアプリが影響を受ける可能性があります。

参考:http://dwij.co.in/increase-heap-size-of-android-application

4

はちょうどあなたのマニフェスト内のアプリケーションタグにandroid:largeHeap="true"を追加します。

+3

このコードは質問に答えるかもしれませんが、どのようにして問題が解決されるのか、および/またはそれがなぜ解決されるのかについての追加の文脈を提供すると、回答の長期的価値が向上します。 – mech

関連する問題