1台のtomcatインスタンスでJavaのウェブアプリケーションを動作させています。ピーク時には1秒間に約30ページ、通常は約15ページが表示されます。
私の環境は
O/S: SUSE Linux Enterprise Server 10 (x86_64)
RAM: 16GB
server: Tomcat 6.0.20
JVM: Java HotSpot(TM) 64-Bit Server VM 1.6.0_14
JVM options:
CATALINA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m
-XX:+UseParallelGC
-Djava.awt.headless=true
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
JAVA_OPTS="-server"
数日間の稼働後、Full GCがより頻繁に発生するようになり、アプリケーションの可用性に深刻な問題となりました。tomcatを再起動すると問題は解消されますが、もちろん5日、10日、30日後には元に戻ります(一貫性はありません)。
再起動前後のFull GCログは、http://pastebin.com/raw.php?i=4NtkNXmi。
これは、6.6 日間のアップタイムでの再起動前のログを示し、フル GC が 2.5 秒を必要とし、~6 秒ごとに発生していたため、アプリが苦しんでいることを示しています。
次に、再起動直後のログを見ると、Full GCは5-10分おきにしか発生しなくなっています。
Full GCが発生している時に、jmap -dump:format=b,file=dump.hprof PID
を使って2つのダンプを取得し(Full GCが発生している時に正確に取得したか、2つのFull GCの間に取得したか不明)http://www.eclipse.org/mat/ で開いたがLeak Suspectsでは何も有用なものは得られませんでした。
なお、OutOfMemoryErrorは一度も発生していません。
次にどこを見るべきか、何かアイデアはありますか?
JVMの様々なオプションを調整することに加えて、VMの新しいリリースにアップグレードすることをお勧めします。新しいバージョンでは、ガベージコレクタがより良く調整されているからです(新しい実験的なものを試す必要もありません)。
また、もしJVMに多くのメモリを割り当てるとGCの実行に必要な時間が増えるというのが(部分的に)本当なら、16GBのメモリ全体を使うか、メモリ占有量を増やすかのトレードオフになるので、まずはすべての値を2倍にして試してみてください。
Xms1024m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m
お問い合わせ先
マッシモ
あなたのケースでは、NewGenのライフサイクルより少し長く生きているオブジェクトがたくさんあるのかもしれません。生存者スペースが小さすぎる場合、彼らはそのままOldGenに移動します。 -XX:+PrintTenuringDistribution
が何らかのヒントになるでしょう。NewGenは十分に大きいので、SurvivorRatio
を減らしてみてください。
また、jconsoleを使用すると、メモリで何が起こっているかをより視覚的に把握することができますので、試してみてください。