Javaのメモリ管理まとめ

2023/11/27に公開

Java8以降のメモリ管理についてまとめる

二つのメモリ領域

JAVAがメモリ管理(オブジェクト)

Heap
New(Young) Old
Eden Survivor0(From) Survivor1(To)

OSがメモリ管理(クラスなどの静的メソッド)

Native memory
Metaspace C heap Thread stack

Heap

Javaプログラムのリソースを管理する領域。New領域とOld領域で構成されている

New領域には三つのメモリ領域が存在し、それぞれの詳細は以下の通り

  • Eden
    最初に割り当てられるメモリ領域
  • Survivor0, Survivor1
    GC後に解放されず、かつOldには行かないデータ割り当てられるメモリ領域
  • Old
    指定回数GCを経験して解放されなかったデータが割り当てられるメモリ領域

Native memory

OSが管理するメモリ領域

  • Metaspace
    Javaのクラス、メソッドなど、永続的に参照される
    静的オブジェクトを管理するメモリ領域
    上限設定がない場合は、OS が扱える上限まで使用可能
    (旧parmanent領域,PermGen (Permanent Generation))
  • C heap
    JavaVM自身のリソースを管理するメモリ領域
  • Thread stack
    スレッド毎に命令の順序をスタックするメモリ領域
    1スレッドにつき1スタックが必要。スタックはデフォルトでは1MBが
    割り当てられる

GCとは

Garbage collectorの略

実行中のプログラムが占有していたメモリ領域のうち不要になったものを自動的に解放し、空き領域として再利用できるようにする

GCの種類

  • MinorGC
    Edenの容量が埋まったら発生
    特定回数GC対象になるとOldに移動させる
  • FullGC
    Oldに割り当てが失敗したタイミングで、old及びnew(young)のメモリを解放

Java Option

GC,ヒープに関連するものを抜粋

以下のコマンドで使用できるオプションを参照可能

java -X
  • Xnoclassgc
    クラスのガベージ・コレクションを無効にする
  • -Xincgc
    増分ガベージ・コレクションを有効にする
  • Xms<size>
    Javaの初期ヒープ・サイズを設定する
  • -Xmx<size>
    Javaの最大ヒープ・サイズを設定する
  • -Xss<size>
    Javaのスレッド・スタック・サイズを設定する

Java -Xで確認できないが、metaspaceの上限設定として、いくつかソースがある設定方法

  • XX:MaxMetaspaceSize
    MetaSpaceの上限を設定

ヒープサイズの確認方法

  • jconsole
  • jstat
  • jmap

などいくつか確認方法があるが、jstatでの確認方法に関して詳細に記載する

ヒープに関するオプション情報は以下の通り

-gc option
ガベージ・コレクションが行われたヒープの統計情報。

S0C: Survivor領域0の現在の容量(KB)S1C: Survivor領域1の現在の容量(KB)S0U: Survivor領域0の使用率(KB)S1U: Survivor領域1の使用率(KB)EC: Eden領域の現在の容量(KB)EU: Eden領域の使用率(KB)OC: Old領域の現在の容量(KB)OU: Old領域の使用率(KB)MC: メタスペースの容量(KB)MU: メタスペースの使用率(KB)CCSC: 圧縮されたクラス領域の容量(KB)CCSU: 使用されている圧縮されたクラス領域(KB)YGC: Young世代のガベージ・コレクション・イベントの数。

YGCT: Young世代のガベージ・コレクション時間。

FGC: フルGCイベントの数。

FGCT: フル・ガベージ・コレクションの時間。

GCT: ガベージ・コレクションの総時間。

公式URL
jstat

Heap の使用量の計算方法

この中から、上記のヒープに当てはまるものを抽出すると

S0U,S1U,EU,OUとなる。

つまりHeapの合計使用量は

S0U + S1U + EU + OU

Example

以下のコマンドで起動されているjava processを確認し、ID(PID:プロセスID)を取得

ps aux | grep java
#or
jps
jstat -gc {ID}

-gcオプションを用いてmemoryを確認

S0C     S1C      S0U     S1U      EC       EU        OC         OU         MC     MU      CCSC   CCSU     YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT
21504.0 16384.0  0.0     16352.9  544256.0 105161.4  165376.0   70504.3   71552.0 69756.4 9344.0 8998.5     17    0.206   3      0.287   -          -    0.493

ヒープを計算すると

0.0[S0U] + 16352.9[S1U] + 105161.4[EU] + 70504.3[OU]) / 1024  = 187MB

となる。

Serverでのdefaultヒープサイズの確認方法

オプションを指定しない場合、defaultの設定が適用されるが、defaultの設定がよくわからなかったので調査した結果、現状、明文化されたJVMのヒープメモリーの文書は存在しないが、コマンドを使用してデフォルトのヒープサイズを確認することができる。

基本的には物理メモリーの1/4になっていることが確認できた。

What is the default max heap size (-Xmx) in Java 8?

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

このように確認できる(約2GB,サーバーメモリーが8GBのサーバーにて)

size_t MaxHeapSize = 2046820352

Discussion