Tomcatで実行しているウェブアプリケーションの最大ヒープサイズが8GBに設定されています。完全なGCを実行させる原因は何ですか?
以下は私のVMの引数です。
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m -Xmx8192m -XX:+UseConcMarkSweepGC"
何のユーザーがアプリにログインしていない場合は、(ガベージコレクションの後に存在する)非洗浄可能なメモリが(約1GB)、非常に低いです。
この状況で、jconsoleを使用してメモリの増加パターンを観察すると、約4GBの一定のメモリが増加し、ガベージコレクタが実行され、メモリが約1GBに再び低下します。このパターンは、ユーザーがログインしなくても続きます。
GCデータを記録すると、次のような状態になります。
2017-02-14T15:30:44.553+0530: 591.922: [GC (Allocation Failure) [PSYoungGen: 1501051K->631966K(1833472K)] 2392189K->1523112K(3030016K), 1.5100144 secs] [Times: user=1.49 sys=0.01, real=1.51 secs]
2017-02-14T15:31:20.335+0530: 627.705: [GC (Allocation Failure) [PSYoungGen: 1553054K->595007K(1842176K)] 2444200K->1570521K(3038720K), 1.3050284 secs] [Times: user=1.27 sys=0.04, real=1.31 secs]
2017-02-14T15:33:33.682+0530: 761.052: [GC (Allocation Failure) [PSYoungGen: 1516095K->556800K(1842176K)] 2491609K->1596474K(3038720K), 1.6957154 secs] [Times: user=1.67 sys=0.03, real=1.69 secs]
2017-02-14T15:33:35.378+0530: 762.748: [Full GC (Ergonomics) [PSYoungGen: 556800K->365446K(1842176K)] [ParOldGen: 1039673K->1196476K(2018304K)] 1596474K->1561923K(3860480K), [Metaspace: 70472K->70472K(1114112K)], 11.2779843 secs] [Times: user=11.13 sys=0.09, real=11.28 secs]
2017-02-14T15:34:56.232+0530: 843.602: [GC (Allocation Failure) [PSYoungGen: 1286534K->216613K(1842176K)] 2483011K->1609875K(3860480K), 1.4938761 secs] [Times: user=1.45 sys=0.05, real=1.50 secs]
それが分かるように、時々フルGCマイナーGCに比べてかなりの時間(11秒)を取った、実行され(約1秒)。
GC中に他のすべてのスレッドが中断されるため、ユーザーがFull GC中にWebアプリケーションにアクセスしようとすると、サーバーは応答しません。
私が知りたかったのは、このフルGCを引き起こすのは何ですか?ログによると、マイナーなGCイベントは割り当て失敗によるもので、Full GCはErgonomics
によるものです。これは何を意味するのでしょうか?
この場合、Full GCが起きないようにする方法はありますか?フリーなヒープスペースが残っています。マイナーGCのためにメモリが大幅に削減されるまでFull GCを遅らせる必要があります。
使用しているすべてのGC関連VMオプション(Xms、MaxGCPauseMillis、コレクタなど)とサーバーの物理メモリを追加してください。休止時間を短くしたい場合は、休止時間が短く長くなるので、完全なgcsを遅らせる方法はありません。だから私のヒープはあなたが達成したい目標(プラスあなたが間違ったコレクションアルゴリズムを使用している)のために大きすぎるように構成されているようです。 –
@ piet.t、vmオプションが質問 –
に追加されました。アプリケーションがコードのどこかで明示的な 'System.gc()'呼び出しを行っている可能性があります。私は、CMSコレクタがちょっと狂っているのを見て、 'System.gc()'の呼び出しの後で常に世界的に完全なGCを実行しています。 GCが '-XX:+ DisableExplicitGC' JVMオプションを通してそのような呼び出しを無視するようにすることができます。 –