「java.lang.OutOfMemoryError:Java heap space」エラーに対処するには?


416

Java 5でクライアント側のSwingアプリケーション(グラフィカルフォントデザイナー)を書いています。最近、メモリ使用量を保守的にしていないため、エラーが発生しています。ユーザーは無制限の数のファイルを開くことができ、プログラムは開いたオブジェクトをメモリに保持します。簡単な調査の結果、5.0 Java仮想マシンなどでエルゴノミクスが見つかりました。Windowsマシンでは、JVMのデフォルトの最大ヒープサイズはと言われています。java.lang.OutOfMemoryError: Java heap space64MB

この状況で、この制約にどのように対処する必要がありますか?

Javaのコマンドラインオプションを使用して最大ヒープサイズを増やすこともできますが、そのためには使用可能なRAMを把握し、起動プログラムまたはスクリプトを作成する必要があります。さらに、有限の最大値まで増やしても、最終的には問題が解決されません。

いくつかのコードを書き直して、オブジェクトをファイルシステムに頻繁に永続化し(データベースを使用することも同じです)、メモリを解放することができます。うまくいくかもしれませんが、たぶんたくさんの仕事です。

上記のアイデアの詳細、または自動仮想メモリのようないくつかの代替手段を示し、ヒープサイズを動的拡張することができれば、それはすばらしいことです。


デフォルトの最大ヒープサイズである64 MBは、J2SE 5.0より前のものです。J2SE 8.0の情報については、docs.oracle.com/javase/8/docs/technotes/guides/vm/…にある「Garbage Collector Ergonomics」を参照してください。
アンディトーマス

すべてのOOMの質問がこの質問にだまされているためにここに着陸した場合は、以下もチェックしてください:stackoverflow.com/questions/299659/… それがOOM前に「ジャストインタイムの」メモリ参照をクリーンアップするためのソリューションを提供します。SoftReferencesは、実際の問題を解決するツールである可能性があります。
Steve Steiner

回答:


244

最終的に、実行しているプラ​​ットフォームに関係なく、使用できるヒープの有限の最大値が常にあります。Windows 32ビットでは、これは2GB(特にヒープではなく、プロセスごとのメモリの総量)です。たまたま、Javaがデフォルトを小さくすることを選択した場合(おそらく、プログラマがこの問題に遭遇して、何をしているのかを正確に調べる必要なく、暴走メモリ割り当てを持つプログラムを作成できないため)。

したがって、これには、必要なメモリ量を決定するため、または使用しているメモリ量を削減するために使用できるいくつかのアプローチがあります。JavaやC#などのガベージコレクションされた言語の一般的な間違いの1つは、使用しなくなったオブジェクトへの参照を保持したり、代わりに再利用できるときに多くのオブジェクトを割り当てたりすることです。オブジェクトがそれらへの参照を持っている限り、ガベージコレクターはオブジェクトを削除しないため、オブジェクトは引き続きヒープ領域を使用します。

この場合、Javaメモリプロファイラーを使用して、プログラム内のどのメソッドが多数のオブジェクトを割り当てているかを判断し、それらが参照されなくなったことを確認する方法があるかどうか、またはそもそもそれらを割り当てない方法があるかどうかを判断できます。私が過去に使用した1つのオプションは "JMP" http://www.khelekore.org/jmp/です。

何らかの理由でこれらのオブジェクトを割り当てていると判断し、参照を回避する必要がある場合(何をしているのかに応じて)、プログラムを起動するときに最大ヒープサイズを増やすだけで済みます。ただし、メモリプロファイリングを実行して、オブジェクトがどのように割り当てられるかを理解したら、必要なメモリの量をよりよく理解する必要があります。

一般に、プログラムが(おそらく入力サイズに応じて)有限のメモリ量で実行されることが保証できない場合は、常にこの問題が発生します。このすべてを使い果たした後でのみ、オブジェクトをディスクなどにキャッシュすることを検討する必要があります。この時点で、何かのために「メモリのXgbが必要」と言う十分な理由があり、改善することによってそれを回避することはできませんアルゴリズムまたはメモリ割り当てパターン。一般に、これは通常、大規模なデータセット(データベースや一部の科学分析プログラムなど)で動作するアルゴリズムの場合にのみ当てはまり、キャッシュやメモリマップIOなどの手法が役立ちます。


6
OpenJDKおよびOracleJDKには、プロファイラ-jvisualvmがバンドルされています。もっと便利にしたいなら、商用のYourkitをお勧めします。
Petr Gladkikh 2013

121

ヒープの最大サイズ-Xmxを設定するコマンドラインオプションを使用してJavaを実行します。

詳細はこちらをご覧ください


3
このパラメーターを永遠に設定する方法は?'gradlew Assemble'コマンドを使用しています。
Dr.jacky 2017年

2
Run-> Run Configurations-> Click on arguments-> inside VM arguments type -Xms1g -Xmx2g
Arayan Singh

2
それが本当の答えです。
nccc

85

プロジェクトごとに、プロジェクトが必要とするヒープ領域を指定できます

以下はEclipse Helios / Juno / Keplerの場合です。

右クリック

 Run As - Run Configuration - Arguments - Vm Arguments, 

次にこれを追加

-Xmx2048m

1
こんにちはbighostkimとcuongHuyToです。「引数」はどこですか。電話してください。Gmailから約2000件の連絡先をダウンロードして保存する必要があります。メモリ不足の例外が原因でクラッシュする
AndroidRaji

@AndroiRaji:実行可能なメイン(「public static void main(String [] args)」)を持つJavaクラス上でマウスを右クリックし、[実行]-[構成の実行]を選択します。次に、「引数」はメインの直後のタブです(メイン、引数、JRE、クラスパス、ソース、環境、共通のタブが表示されます)。
CuongHuyTo 2014年

47

ヒープサイズの増加は「修正」ではなく、「プラスター」であり、100%一時的なものです。別の場所で再びクラッシュします。これらの問題を回避するには、高性能のコードを記述します。

  1. 可能な限りローカル変数を使用してください。
  2. 正しいオブジェクトを選択していることを確認してください(例:String、StringBuffer、StringBuilder間の選択)
  3. プログラムに適切なコードシステムを使用する(例:静的変数と非静的変数の使用)
  4. あなたのコードで動作する可能性のある他のもの。
  5. マルチスレッドで動くようにしてください

信用できる。AWTスレッドでOOMが発生する問題を修正しようとしていますが、別の新しいスレッドを使用すると、OOMの問題が発生しません。オンラインで見つけることができるのは、AWTスレッドのヒープサイズを増やすことだけです。
アシッシュ

@灰:はい、石膏を探すのではなく、コアの問題を修正します。
レモンジュース

Javaでのガベージコレクションとメモリ管理アプローチは、その前任者のこれらのmalloc-deallocの複雑さをすべて解決するはずでした:(もちろん、私はこの答えに完全に同意します。 -できるだけ早くクリーンアップされた構造
Davos

31

大きな警告----私のオフィスでは、(一部のWindowsマシンでは)Javaヒープに512mを超える割り当てができないことがわかりました。これは、一部のマシンにインストールされているKasperskyアンチウイルス製品が原因であることが判明しました。そのAV製品をアンインストールした後、少なくとも1.6 GBを割り当てることができることがわかりました。 -Xmx1600m( mは必須です。

これが他のAV製品で発生するかどうかはわかりませんが、AVプログラムがすべてのアドレス空間で小さなメモリブロックを予約しているため、単一の実際に大きな割り当てができないために発生していると考えられます。


22

VM引数は日食で私のために働きました。Eclipseバージョン3.4を使用している場合は、次の手順を実行します

移動しRun --> Run Configurations -->、mavenビルドの下のプロジェクトを選択します->次に、「JRE」タブを選択し、次にを入力し-Xmx1024mます。

または、次のようRun --> Run Configurations --> select the "JRE" tab -->に入力することもできます-Xmx1024m

これにより、すべてのビルド/プロジェクトのメモリヒープが増加します。上記のメモリサイズは1 GBです。必要に応じて最適化できます。


18

はい、-XmxJVMにより多くのメモリを構成できます。メモリをリークしたり、無駄にしないようにしてください。ヒープダンプを取得し、Eclipse Memory Analyzerを使用てメモリ消費を分析します。


JVMJ9VM007Eコマンド行オプションが認識されません:-Xmx Java仮想マシンを作成できませんでした。反対投票
Philip Rego

17

オラクルのトラブルシューティングからの推奨事項を追加したい記事ます。

スレッドthread_nameの例外:java.lang.OutOfMemoryError:Java heap space

詳細メッセージのJavaヒープスペースは、オブジェクトをJavaヒープに割り当てることができなかったことを示します。このエラーは必ずしもメモリリークを意味するものではありません

考えられる原因:

  1. 単純な構成の問題。指定されたヒープサイズではアプリケーションには不十分です。

  2. アプリケーションが誤ってオブジェクトへの参照を保持しているため、オブジェクトがガベージコレクションされるのを防ぎます。

  3. ファイナライザの過度の使用

このエラーのもう1つの潜在的な原因は、ファイナライザを過度に使用するアプリケーションで発生します。クラスにfinalizeメソッドがある場合、そのタイプのオブジェクトには、ガベージコレクション時にスペースが再利用されません。

ガベージコレクションの後、オブジェクトはファイナライズのためにキューに入れられます。これは後で発生します。 ファイナライザは、ファイナライズキューを処理するデーモンスレッドによって実行されます。ファイナライザスレッドがファイナライズキューに追いつけない場合、Javaヒープがいっぱいになり、このタイプのOutOfMemoryError例外がスローされます。

この状況を引き起こす可能性のあるシナリオの1つは、ファイナライザスレッドがそのキューを処理する速度よりも速い速度でファイナライズキューを増加させる高優先度のスレッドをアプリケーションが作成する場合です。


9

以下の手順に従ってください:

  1. catalina.shtomcat / binから開きます。

  2. JAVA_OPTSを

    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m 
    -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
  3. Tomcatを再起動します


8

私はあなたが試すことができるどこか他の場所を読みました-java.lang.OutOfMemoryErrorをキャッチし、catchブロックで、多くのメモリを使用している可能性があるすべてのリソースを解放し、接続を閉じるなどしてから、 System.gc()何でも再試行してくださいあなたがやるつもりでした。

別の方法はこれですが、これが機能するかどうかはわかりませんが、現在、アプリケーションで機能するかどうかをテストしています。

アイデアは、空きメモリを増やすことが知られているSystem.gc()を呼び出してガベージコレクションを行うことです。あなたは、コードを実行しているメモリを実行した後、これをチェックし続けることができます。

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

6
一般的に、JVMはOutOfMemoryErrorをスローするのではなく、ガベージコレクト(GC)を優先するように思います。OutOfMemoryErrorの後に明示的にSystem.gc()を呼び出すと、一部のVM /構成で役立つ可能性がありますが、一般的なケースではうまく機能しないと思います。ただし、不要なオブジェクト参照を削除すると、ほぼすべてのケースで間違いなく役立ちます。
Mike Clark、

6
@mwangiコードから直接System.gc()を呼び出すことは、一般に悪い考えです。GCを実行する必要があることはJVMへの提案にすぎませんが、実行される保証はありません

7

OutOfMemoryErrorJavaで解決する簡単な方法は、JVMオプションを使用して最大ヒープサイズを増やすこと-Xmx512Mです。これにより、OutOfMemoryErrorがすぐに解決されます。プロジェクトのサイズに基づいてメモリが簡単に不足する可能性があるため、プロジェクトのビルド中にEclipse、Maven、またはANTでOutOfMemoryErrorが発生した場合、これが私の推奨ソリューションです。

JVMの最大ヒープサイズを増やす例を次に示します。Javaアプリケーションでヒープサイズを設定している場合は、-Xmxと-Xmsの比率を1:1または1:1.5に維持することをお勧めします。

export JVM_ARGS="-Xms1024m -Xmx1024m"

参照リンク


1
それらを1:1または1:1.5の比率に保つ必要がある理由は何ですか?
ernesto 2012年

7

開発用のデフォルトでは、JVMは他のパフォーマンス関連機能に小さなサイズと小さな構成を使用します。しかし、本番環境では、たとえば(アプリケーションサーバー固有の構成が存在する場合もあります)を調整できます->(まだメモリが不足していて要求を満たすことができず、ヒープがすでに最大サイズに達している場合、OutOfMemoryErrorが発生します)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)

例:Linuxプラットフォームの本番モードの望ましい設定。

この方法でサーバーをダウンロードして構成した後http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1. / opt / tomcat / bin /フォルダーにsetenv.shファイルを作成します

   touch /opt/tomcat/bin/setenv.sh

2.このパラメーターを開いて書き込み、望ましいモードを設定します。

nano  /opt/tomcat/bin/setenv.sh 

export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"

3。service tomcat restart

JVMはヒープよりも多くのメモリを使用することに注意してください。たとえば、Javaメソッド、スレッドスタック、ネイティブハンドルは、JVM内部データ構造と同様に、ヒープとは別のメモリに割り当てられます。


7

私はJavaヒープサイズから同じ問題に直面しています。

Java 5(1.5)を使用している場合、2つの解決策があります。

  1. jdk1.6をインストールしてeclipseの設定に移動し、インストールしたとおりにjav1 1.6のjreパスを設定します。

  2. VM引数を確認し、それが何であれそれをしましょう。-Xms512m -Xmx512m -XX:MaxPermSize = ... m(192m)としてVM引数に存在するすべての引数の下に1行追加するだけです。

うまくいくと思います...


7

実行時にメモリ使用量を監視する必要がある場合は、VMのメモリプール(エデンスペース、テニュアジェネレーションなど)とガベージコレクションの動作を監視するために使用できるjava.lang.managementパッケージが提供MBeansされます。

これらのMBeanによって報告される空きヒープ領域は、特にアプリケーションが後でGCされるオブジェクトを大量に生成する場合、GCの動作によって大きく異なります。1つの可能なアプローチは、各フルGCの後に空きヒープ領域を監視することです。これを使用して、オブジェクトを永続化することによってメモリを解放するかどうかを決定できます。

最終的には、パフォーマンスを許容できる範囲でメモリの保持を可能な限り制限することが最善の策です。以前のコメントで述べたように、メモリは常に制限されていますが、アプリにはメモリの枯渇に対処するための戦略が必要です。


5

デプロイメントの状況でこれが必要な場合は、Java WebStartの使用を検討してください(ネットワークバージョンではなく、「ondisk」バージョンを使用-Java 6u10以降で可能)。クロスでJVMにさまざまな引数を指定できるためです。プラットフォームの方法。

それ以外の場合は、必要な引数を設定するオペレーティングシステム固有のランチャーが必要になります。


Java WebStartは段階的に廃止されます。私はまだ適切な代替品を知りません。
するThorbjörnRavnアンデルセン

1

この問題がWildfly 8とJDK1.8で発生している場合は、PermGen設定ではなくMaxMetaSpace設定を指定する必要があります。

たとえば、wildflyのsetenv.shファイルに以下の設定を追加する必要があります。 JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"

詳細については、Wildflyヒープの問題を確認してください


1

netbeansに関しては、問題を解決するために最大ヒープサイズを設定できます。

「実行」に移動し、次に->「プロジェクト構成の設定」->「カスタマイズ」->ポップアップウィンドウの「実行」->「VMオプション」->「-Xms2048m -Xmx2048m」と入力します。 。


1

オブジェクトへの参照の割り当てと保持を続けると、所有しているメモリがいっぱいになります。

1つのオプションは、タブが切り替わったときに透過的なファイルを閉じて開くことです(ファイルへのポインターを保持するだけで、ユーザーがタブを切り替えたときにすべてのオブジェクトを閉じてクリーニングします...ファイルの変更が遅くなります)。 ...しかし...)、そしておそらくメモリに3つまたは4つのファイルのみを保持します。

他にすべきことは、ユーザーがファイルを開いてロードし、OutOfMemoryErrorをインターセプトした場合、(ファイルを開くことができないため)そのファイルを閉じ、オブジェクトをクリーンアップして、未使用のファイルを閉じるようユーザーに警告することです。ファイル。

マシンがリソースに制限されているため、仮想メモリを動的に拡張するという考えは問題を解決しません。そのため、メモリの問題に注意して対処する必要があります(少なくとも、それらに注意してください)。

私がメモリリークで見たいくつかのヒントは次のとおりです:

->何かをコレクションに入れた後でそれを忘れた場合でも、そのコレクションへの強い参照があるので、コレクションを無効にするか、クリーンアップするか、何かを行うことを忘れないでください...見つからない場合は、見つけにくいメモリリーク。

->たぶん、弱い参照(weakhashmap ...)のコレクションを使用するとメモリの問題を解決できる可能性がありますが、探しているオブジェクトが収集されていることに気付く可能性があるため、注意が必要です。

->私が見つけた別のアイデアは、使用頻度が最も低く、透過的にロードされたデータベースオブジェクトに格納された永続的なコレクションを開発することです。これはおそらく最良のアプローチでしょう...


0

他のすべてが失敗した場合は、最大ヒープサイズを増やすことに加えて、スワップサイズも増やしてみてください。Linuxの場合、現時点では、関連する手順はhttps://linuxize.com/post/create-a-linux-swap-file/にあります

これは、たとえば組み込みプラットフォームで何か大きなものをコンパイルする場合に役立ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.