Knowledge‎ > ‎

JavaのGCログの意味

GCログがこんなふうに出ているとき

18154K->2311K(24576K)
【A】 ->【B】(【C】)

【A】がGC前のヒープ使用量
【B】がGC後のヒープ使用量
【C】が現在VMが確保しているメモリ量

こんな説明をしているサイトを多く見かけます。私もこれが正しいと思っていました。そしてVMが一度確保したメモリ量は減ることはない、つまり【C】は決して減ることはないものだと思っていました。

しかし、【C】の値を元にMRTGでグラフ描画して監視していたところ、-Xmsと-Xmxを同じ値にしているにもかかわらず、軽く増減している現象を見つけました。ログを見ると確かに一定の範囲内を微妙に増減していました。これをきっかけに詳しく調べてみました。


oracleの公式ページに詳しい説明があります。

3.2
The number in parenthesis is the total available space,
not counting the space in the permanent generation,
which is the total heap minus one of the survivor spaces.

括弧内の数字は利用可能な総容量であり、
永続的に使用される領域をカウントしていません。
それはヒープの総計からsurvivor領域のひとつを引いた値です。

The next number in parentheses is the committed size of the heap: 
the amount of space usable for java objects without requesting more memory from the operating system.

Note that this number does not include one of the survivor spaces, 
since only one can be used at any given time, and also does not include the permanent generation, 
which holds metadata used by the virtual machine.

括弧内の次の数字は、ヒープのコミットサイズです。
これはOSへの追加要求無しに、Javaオブジェクトが使用可能な量です。

気をつけなければならないのは、この数字はSurvivor領域の一つ分が含まれていないことです。
Survivor領域は任意の時点で使用することができるのは1つだけで、永続的な世代が含まれていません。
仮想マシンが使用するメタデータとして保持しています。
※どちらも三浦訳。英語には自信がありません。間違い等ありましたらご指摘よろしくお願いします。

つまり簡単に言えば、VMが確保しているサイズではなく使用可能なサイズを示しているということです。

そして、このSurvivior領域のサイズは、Java5.0以降のデフォルトの設定ではGCのたびに自動的に調節され変化します(変化しないようにすることも可能:-XX:-UseAdaptiveSizePolicy)。このため、デフォルトの設定では、全体から引く分のサイズも動的に変化することになるため、使用可能な領域は増減するのです。

「Survivor領域ってなに?」という方は、上記のサイトの説明や他のサイトでGCの基本的な仕組みを勉強してください。


簡単にまとめるとこんな感じです。
  • VMが確保したメモリ量≠Javaで使用可能なメモリ量
  • VMが確保したメモリ量-Javaで使用できないメモリ量=Javaで使用可能なメモリ量
  • 【C】≠VMが確保したメモリ量
  • 【C】=Javaで使用可能なメモリ量
  • 【C】はGC後に減ることがある
  • Java5.0以降のデフォルトの設定では、 Survivor領域のサイズがGCのたびに調節される

このような理由で、この値を基準にMRTGでグラフを描画しているとガタガタになります。