10

私はJavaを実行していますjava -Xmx240g mypackage.myClass

OSはUbuntu12.10です。

topMiB Mem 245743 total、Java プロセスがvirt 254g最初からあり、resまで着実に増加していることを示してい169gます。その時点でガベージ コレクションが大量に開始されるように見えますが、その時点でプログラムはシングル スレッドであり、CPU%ほとんど100%がこの時点までであり、この時点で約 1300 ~ 2000 にジャンプするためだと思います (私はそれがマルチスレッド ガベージ コレクタ)、resゆっくりと に移動し172gます。その時点でJavaはクラッシュします

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

との行でnew double[2000][5]

java -version言う

java version "1.7.0_15" OpenJDK Runtime Environment (IcedTea7 2.3.7) (7u15-2.3.7-0ubuntu1~12.10) OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

ハードウェアは Amazon cr1.8xlarge インスタンス

利用可能なメモリがたくさんある場合でも、Java がクラッシュするように思えます。明らかに不可能です。いくつかの数字を間違って解釈する必要があります。何が起こっているのかを理解するには、どこを見ればよいですか?

編集:

GC オプションは指定しません。唯一のコマンドラインオプションは-Xmx240g

私のプログラムは多くの入力を正常に処理しtopており、最大 98.3% のメモリを使用していると言われています。ただし、特定のプログラム入力で上記の状況を再現しました。

編集2:

これは科学的応用です。巨大なツリー (100 万から 1000 万のノード) があり、各ノードにはdoubleサイズが約 2 つの配列があります。300x3 - 900x5。最初のツリー作成後、プログラムは多くのメモリを割り当てません。ほとんどの場合、これらの配列に対していくつかの算術演算が行われます。

編集3:

HotSpot JVM も同じように停止し、CPU を 170 ~ 172g マークで大量に使用し、同じエラーでクラッシュしました。メモリの 70 ~ 75% は、JVM が越えたくない魔法の境界線のようです。

最終的な解決策: -XX:+UseConcMarkSweepGC -XX:NewRatio=12 の場合、プログラムは 170g のマークを通過し、さらに進んでいます。

4

3 に答える 3

9

分析

最初に行う必要があるのは、JVM がクラッシュしたときにヒープがどのように見えるかを正確に把握できるように、ヒープ ダンプを取得することです。次の一連のフラグをコマンド ラインに追加します。

-XX:+HeapDumpOnOutOfMemoryError -verbose:gc -XX:+PrintGCDetails

クラッシュが発生すると、JVM はヒープをディスクに書き出そうとします。率直に言って、そのサイズのヒープでは長い時間がかかります。Eclipse MATをダウンロードするか、既に Eclipse を実行している場合はプラグインをインストールします。そこから、ヒープ ダンプを読み込んで、既定のレポートをいくつか実行できます。Leak Suspects と Dominator Tree をチェックして、メモリがどこに向かっているのかを確認し、実際のリークがないことを確認する必要があります。

その後、ガベージ コレクションに関するオラクルのこのドキュメントを読むことをお勧めしますが、考慮できる点がいくつかあります。

同時GC

-XX:+UseConcMarkSweepGC 

そのサイズのヒープで並列のみのコレクターを使用して逃げ出した人は聞いたことがありません。コンカレント コレクターを有効にすると、インクリメンタル モードを調べて、ワークロードとハードウェアの組み合わせに適しているかどうかを判断する必要があります。

ヒープフリー率

-XX:MinHeapFreeRatio=25

フル コレクションを実行する場合、ガベージ コレクタのバーを下げるには、これをダイヤルダウンします。これにより、完全なコレクションを実行してメモリ不足になるのを防ぐことができます。40% がデフォルトです。より小さい値で試してください。

新しい比率

-XX:NewRatio

実際のワークロードについて詳しく聞く必要があります。これはウェブアプリですか? スイングアプリ?オブジェクトがヒープ上で存続すると予想される期間に応じて、新しい比率値に影響を与えます。あなたが実行しているようなサーバー モードの VM は、既定でかなり高い新しい比率 (8:1) を持っています。これは、有効期間の長いオブジェクトがたくさんある場合には理想的ではないかもしれません。

于 2013-04-19T01:38:03.627 に答える
1

一般的なアドバイスとして、OpenJDK は絶対に使用しないでください。本番環境ではさらに少なく、Sun/Oracle のものよりもはるかに低速です。

それとは別に、VM が非常に多くのメモリを使用しているのを見たことがありませんが、それはあなたが必要としているものだと思います (または、必要以上のメモリを使用するコードを持っているのではないでしょうか?)

編集:サーバー用のOpenJDKは問題ありません。Sun/Oracle JDKとの違いはデスクトップのもの(サウンド、GUI ...)に関するものだけなので、その部分は無視してください。

于 2013-04-19T01:03:08.177 に答える