以下は私のJVM設定です:
Java_OPTS=-server -Xms2G -Xmx2G -XX:MaxPermSize=512M -Dsun.rmi.dgc.client.gcInterval=1200000 -Dsun.rmi.dgc.server.gcInterval=1200000 -XX:+UseParallelOldGC -XX:ParallelGCThreads=2 -XX:+UseCompressedOops -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jbos88,server=y,suspend=n
問題:合計ヒープメモリ:2GB古い世代:1.4GB(ヒープの2/3)新しい世代:600MB(ヒープの1/3)
Old Genは、割り当てられたサイズの70%を超えてメモリ内で増加し、100%、つまり1.4GBでもGCの影響を受けません。下のグラフがピークになり、GCになることはありません。メモリの低下は、JConsoleから強制的にGCされたときです。この問題により、最終的にWebサーバーがダウンします。
JVMが設定されていない、または間違って設定されているものはありますか?
事前に助けてくれてありがとう。
私の質問の更新:
ヒープ分析後、ステートフルセッションBeanが最も疑わしいと思われます。 Hibernateが支援する永続ロジックを保持するステートフルセッションBeanがあります。
ステートフルセッションBeanにより、JVMのメモリが不足していました。 @Removeアノテーションを使用して明示的に処理することで、この問題は解決しました。
GCは最終的に呼び出され、古い生成はほとんど呼び出されません(非常に遅いため)。 GCは実行されますが、最初は新しい世代と生存者の世代でのみ実行されます。古い世代をクリーンアップするためのアルゴリズムは、新しい世代または生存者の世代よりも遅く、まったく異なります。
それらの数は本当に高いので、oldgenはnewgenと比較して合計数が高くなることはありません。私の推測では、メモリリークがあります。
私はあなたのプログラムが大きなファイルを扱っていると推測することができるだけで、おそらくそれらへの参照をあまりにも長く保存しているでしょう。
それでも主な問題(メモリリーク)が解決されたとしても、古い世代を頻繁に小さな一時停止でクリアしたい場合は、設定を試すことができます
-XX:MaxGCPauseMillis=(time in millis)
これは、Parallel Collectorで、適応型サイジングポリシーがオンの場合にのみ適用されます。デフォルトではアダプティブサイジングポリシーがオンになっていますが、これを明示的に言及したい場合は使用できます。
-XX:+UseAdaptiveSizePolicy
または、使用できるCMSコレクターに切り替えることができます
-XX:CMSInitiatingOccupancyFraction=(% value)
-XX:+UseCMSInitiatingOccupancyOnly
これは、古い世代の一定の割合に達したときに古い世代を収集するためのより信頼できる方法です。