Java再入門 JVMオプション

JVMオプションについてのまとめです。
以下が前提になっているので、前提が合わない場合はスルーしてください。

* サーバサイドのオンライン処理や常駐処理向けに書いています。
* 想定しているJavaのバージョンは11です。
* リソースは結構贅沢に割り当てられる環境です。

# JITコンパイラ

| 設定値                                                       | 開発 | 性能 | 本番 | 用途                                                         |
| ------------------------------------------------------------ | ---- | ---- | ---- | ------------------------------------------------------------ |
| server                                                       | ○    | ○    | ○    | 長時間実行されるアプリケーションの推奨設定                   |
| XX:+TieredCompilation                                        | ○    | ○    | ○    | サーバーコンパイラの動作改善                                 |

# メモリ

## JVMが使用するメモリの全体像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/bec2772a-dd61-1d0a-219f-df72c759f995.png)

|                       | 上限の設定方法           | 設定の考え方とメモリ消費量                                   |
| --------------------- | ------------------------ | ------------------------------------------------------------ |
| ヒープ                | Xmx                      | 4GB以上を割り当てる                                          |
| Metaspace             | XX:MaxMetaspaceSize      | 指定しない状態で稼働させて、jcmd プロセスID VM.native_memory summaryの出力結果のClass  reservedの値に100MBを加えた値を設定する |
| OS領域/Codeキャッシュ | XX:ReservedCodeCacheSize | 環境によってデフォルト値が異なるが、初期値として240MBを名指しする。一通りの処理を10回程度呼び出したあと、jcmd プロセスID VM.native_memory  summaryの出力結果のCodeのcommittedをみて足りていない場合はチューニングする |
| OS領域/Thread         | Xss ※スレッド毎の上限    | Xssには1MBを指定する。Tomcatだけで200スレッド利用する。コネクションプールもプール数分、スレッドを消費する。jcmd プロセスID VM.native_memory summaryの出力結果のThread  reservedの値に50MB（50スレッド分のバッファ）を加えた値を消費量とみなす |
| OS領域/その他         |                          | jcmd プロセスID VM.native_memory  summaryの出力結果のThread、Heap、Class、Code以外の値にバッファとして100MBを加えた値を消費量とみなす |

## ヒープの領域別のチューニング方法

* 各領域の比率はデフォルトだと自動で調整される（Adaptive Sizing）。
* G1GCのチューニング方法は後述する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/80a28e9f-4a55-3e10-65c9-60e9fc15b9dd.png)

|                         | **意味**                         | **初期値**             | **チューニングの考え方**                                     |
| ----------------------- | -------------------------------- | ---------------------- | ------------------------------------------------------------ |
| Xms                     | ヒープの最小値                   | 物理メモリから計算 | Xms = Xmxにする。4GB以上を割り当てる。  ヒープが大きいとGCの頻度は減るが、時間は長くなる。 |
| Xmx                     | ヒープの最大値                   | 物理メモリから計算 |                                                              |
| XX:NewRatio             | ヒープ全体のYoung領域の比率      | Server  VMは2          | G1GCの場合は指定すると、XX:MaxGCPauseMillisを使ったチューニングが効果を発揮しなくなるので触ってはいけない。 |
| XX:InitialSurvivorRatio | Young領域内のS領域の比率の初期値 | 8                      | 短命なオブジェクトの昇格が頻繁な場合                         |
| XX:MinSurvivorRatio     | Young領域内のS領域の比率の最小値 | 3                      | メモリに余裕があるなら、そもそものHeapサイズを増やす方が良い。  Heapサイズを増やせない場合のチューニング方法は後述する。 |

## G1GCのチューニングの考え方

これは日立さんがG1GCのチューニングについて書いている記事を参考にしつつ自分なりに整理してみました。
フローチャートは日立さんのページからの引用です。

http://itdoc.hitachi.co.jp/manuals/link/cosmi_v0970/03Y0460D/EY040199.HTM

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/1a08d479-94b8-d096-9bb6-3a0c9ae7c808.png)

1. FullGCが発生している場合
    * GCのログにHumongousが出力されている
        * アプリケーションの修正をする。
        * これができない場合は割り当てるヒープサイズを8GB以上にする（8GBの次は16GBになってしまう）。
    * GCのログにto exhaustedが出力されている
        * ヒープサイズを大きくすることをまずは検討する。
        * ヒープサイズを大きくできない場合はMinSurvivorRatioを大きくすることを検討する。副作用でEden領域が減る。
1. 上記のいずれでもない
    * XX:ConcGCThreadsとXX:ParallelGCThreadsを指定して、GCで利用できるスレッド数を増やして空き容量を確保する。CPUも追加することが望ましい。
1. FullGCが発生していない場合
    * スループットを改善したい時→MaxGCPauseMillisを大きくする
    * 最悪レスポンス時間を改善したい時→MaxGCPauseMillisを小さくする


## その他のメモリ関連オプション

OutOfMemory発生時にヒープダンプを出力し、アプリケーションを停止させるために必要だが、コンテナの中で利用する場合は吐き出し先がない。

| 設定値                                                       | 開発 | 性能 | 本番 | 
| ------------------------------------------------------------ | ---- | ---- | ---- | 
| XX:HeapDumpPath                                              | ○ | ○ | ○ |  
| XX:+HeapDumpOnOutOfMemoryError                               | ○ | ○ | ○ |  
| XX:+CrashOnOutOfMemoryError                                  | ○ | ○ | ○ |  

# GC

| 設定値                                                       | 開発 | 性能 | 本番 | 用途                                                         |
| ------------------------------------------------------------ | ---- | ---- | ---- | ------------------------------------------------------------ |
| XX:+UseG1GC                                                  | ○    | ○    | ○    | 低スペックマシンでも本番と同じG1を利用するため               |
| XX:MaxGCPauseMillis                                          |      | ○    | ○    | デフォルトは200。GCの目標停止時間<br />チューニングの考え方はG1GCのチューニングを参照                              |
| XX:ParallelGCThreads                                         |      | ○    | ○    | G1GCに割り当てるスレッド数を指定する。                       |
| XX:ConcGCThreads                                             |      | ○    | ○    | ※CPUに余裕がある場合でGCの影響を緩和した時                   |

# モニタリング

| 設定値                                                       | 開発 | 性能 | 本番 | 用途                                                         |
| ------------------------------------------------------------ | ---- | ---- | ---- | ------------------------------------------------------------ |
| verbose:gc                                                   | ○    | ○    | ○    | GC実行状況の可視化                                           |
| XX:+PrintGCDetails                                           | ○    | ○    | ○    | Xloggcを指定しなければ標準出力に出る                         |
| XX:StartFlightRecording=delay=1m,maxsize=500m,settings=default |      |      | ○    | 性能問題調査に必要。JFRの有効化<br />性能影響は1%と言われている。 |
| XX:StartFlightRecording=delay=1m,maxsize=500m,settings=profile | ○    | ○    |      | 性能問題調査に必要。JFRの有効化<br />性能影響は2%と言われている。 |
| XX:NativeMemoryTracking=summary                              | ○    | ○    |      | メモリ使用量の確認に必要<br />性能影響は5～10%と言われている。 |

# その他

| 設定値                                                       | 開発 | 性能 | 本番 | 用途                                                         |
| ------------------------------------------------------------ | ---- | ---- | ---- | ------------------------------------------------------------ |
| XX:-UseBiasedLocking                                         | ○    | ○    | ○    | 左記のフラグで無効にする。スレッドのロック競合を複雑な仕組みでチューニングするため副作用が大きい。 |

# シリーズJava再入門

いまからJava8にしよう！だってJava11よりサポート長いし！という判断もあると思いますが、11に引っ越そうとしている方や、11の次のLTSになることを予定されている17への移行を目指している方向けのJava再入門です。

1. [Java7以降の歴史 機能追加とサポート期間](https://qiita.com/yyukawa/items/e1a027bcbfbb3d39958e)
1. [モジュールシステムとクラスパス、Gradle](https://qiita.com/yyukawa/items/44ef24f51649e6c5e299)
1. [Java再入門 JVMオプション](https://qiita.com/yyukawa/items/96f667c7f0c06f97ed3e)
1. [Java再入門 ～Java11 ジェネリクス、ダイアモンド演算子](https://qiita.com/yyukawa/items/d5a5ab8d4846c0b70479)
1. [Java再入門 ～Java11 日付時刻API](https://qiita.com/yyukawa/items/d4159506da46bbd6b651)
1. ～Java11 リソース付きtry文
1. ～Java11 ラムダ式、メソッド参照、Stream、Optional、ローカル変数型推論
1. ～Java11 ExecutorService/Future、Fork/Join
1. 今後：テキストブロック
1. 今後：switch式、パターンマッチングinstanceof
1. 今後：record