497

Java 5でクライアント側のSwingアプリケーション (グラフィカル フォント デザイナー) を作成しています。最近、メモリ使用量を控えめにしていないため、エラーが発生しています。ユーザーは無制限の数のファイルを開くことができ、プログラムは開いたオブジェクトをメモリに保持します。簡単な調査の後、私は 5.0 Java Virtual Machine の Ergonomicsや、Windows マシンで JVM のデフォルトの最大ヒープ サイズが.java.lang.OutOfMemoryError: Java heap space64MB

この状況を考えると、この制約にどのように対処すればよいですか?

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

オブジェクトをファイル システムに頻繁に保持するようにコードの一部を書き直して (データベースの使用も同じことです)、メモリを解放することができます。うまくいくかもしれませんが、おそらく大変な作業でもあります。

上記のアイデアの詳細や、ヒープサイズを動的に拡張する自動仮想メモリなどの代替案を教えていただければ、それは素晴らしいことです。

4

30 に答える 30

281

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

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

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

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

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

于 2008-09-01T01:29:54.457 に答える
142

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

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

于 2008-09-01T05:00:01.927 に答える
97

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

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

マウスの右クリック

 Run As - Run Configuration - Arguments - Vm Arguments, 

次に、これを追加します

-Xmx2048m
于 2011-02-25T18:45:31.840 に答える
62

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

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

大きな注意点 ---- 私のオフィスでは、(一部の Windows マシンでは) Java ヒープに 512m 以上を割り当てることができないことがわかりました。これは、これらのマシンの一部にインストールされた Kaspersky アンチウイルス製品が原因であることが判明しました。その AV 製品をアンインストールした後、少なくとも 1.6 GB を割り当てることができることがわかりました。つまり、 -Xmx1600m(m は必須です。そうしないと、「初期ヒープが小さすぎます」という別のエラーが発生します) 動作します。

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

于 2009-04-14T13:34:15.210 に答える
23

VMの引数はEclipseで機能しました。Eclipseバージョン3.4を使用している場合は、次のようにします

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

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

これにより、すべてのビルド/プロジェクトのメモリヒープが増加するはずです。上記のメモリサイズは1GBです。あなたはあなたが望む方法を最適化することができます。

于 2011-06-09T20:48:29.717 に答える
23

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

スレッド thread_name での例外: java.lang.OutOfMemoryError: Java ヒープ領域

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

考えられる原因:

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

  2. アプリケーションが意図せずにオブジェクトへの参照を保持しているため、オブジェクトがガベージ コレクションされません。

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

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

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

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

于 2016-03-22T18:35:19.573 に答える
19

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

于 2008-10-09T08:22:25.737 に答える
11

以下の手順に従います。

  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 を再起動します

于 2013-10-07T10:56:05.433 に答える
9

私はあなたが試すことができる他の場所を読みました-catch 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();
于 2010-08-17T07:30:25.990 に答える
9

開発用のデフォルトでは、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 内部データ構造と同様に、ヒープとは別のメモリに割り当てられます。

于 2016-05-26T12:00:49.180 に答える
8

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

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

export JVM_ARGS="-Xms1024m -Xmx1024m"

参照リンク

于 2011-09-04T05:05:07.650 に答える
7

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

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

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

于 2008-10-09T12:04:30.030 に答える
5

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

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

于 2009-05-19T04:45:22.303 に答える
1

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

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

他にすべきことは、ユーザーがファイルを開いてロードし、OutOfMemoryError をインターセプトしてから (ファイルを開くことができないため)、そのファイルを閉じ、そのオブジェクトを消去し、未使用で閉じる必要があることをユーザーに警告することです。ファイル。

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

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

--> コレクションに何かを入れた後、それを忘れたとしても、それへの強い参照がまだ残っていることに注意してください。そのため、コレクションを無効にするか、クリーンアップするか、何かを行います... そうしないと、見つけにくいメモリリーク。

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

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

于 2010-09-29T07:47:13.120 に答える
0

Android スタジオ

ファイル - >キャッシュを無効にして再起動することで解決しました:)

于 2021-03-14T13:35:53.727 に答える