2025年令和最新版 BMSオタクのJDK・JVMオプション考
beatorajaのJDKを更新したりJVMオプションについて調べたりする記事です。自分用のメモ書きを兼ねているので読みにくかったらすみません。
前提
みんなこの記事は見てると思います:【2023年版】beatoraja を Windows にインストールする方法【BMS】
以下、この記事を読んだ前提の説明を書いていきます。
これを書いた人は職業エンジニアですが非情報専攻です。JavaについてはちょっとKotlin触るくらいで、どちらかというとスプレッドシートから出力される難易度表へアクセスするときの遅さの方が気になる人。
筆者環境
| OS | Windows 10 Pro |
| CPU | AMD Ryzen 7 5800X |
| GPU | NVIDIA GeForce RTX 3070 |
| ディスプレイ | Dell AW2521H |
| beatoraja | 0.8.8 |
| JDK(更新前) | Amazon Corretto 17.0.2 |
結論
JRE同梱版をインストールしている人:あんまり凝りたくない方だと思うので海岸砂丘さんのツイートに従ってください、この記事読む必要なし
上の記事に従ってインストールしている人:JDK 25を入れる。落としてきたところはOracle OpenJDK 25.0.1とJava FX 25.0.1
beatoraja-config.batの起動コマンドやJVMオプションは以下
start /abovenormal /wait /b jdk/bin/java -Xms4g -Xmx4g --module-path javafx-sdk/lib --add-modules=javafx.controls,javafx.fxml -XX:+UseZGC -XX:+AlwaysPreTouch -XX:+UseLargePages -XX:-UsePerfData -jar beatoraja.jar
説明
JDKのバージョンについて
2025年9月にLTS(2033年までの長期サポート版)であるJava 25がリリースされました。更新するなら今!!ついでにパソコンも買え!!!(手遅れ)
まあぶっちゃけ個人でゲーム用に入れるのにサポート期間も何も関係ないしJDK 17とかなら無理に更新せんでもいいとは思いますが、上記の記事より一応性能がよくなりそうなので。
JDKの入手先について
しらね~~~~~~~
元記事ではAmazon Correttoが良いんじゃないかとか書かれてますが、好きなところから落としてくればいいと思います。性能差はたぶん全くない。
ただ、Liberica Full JDK 25などのJava FX同梱版JDKを入れると--module-path, --add-modulesなどで個別にインストールしたJava FXを指定する手間は無くなります。今後の更新作業を考えるとFX同梱の方が楽かも。性能差はたぶん全くない(2)のでお好みでチャレンジしてみてね(筆者未検証)。
ちなみに現在Mocha-Repositoryで配布されているbeatoraja-0.8.8-jre-win64はLiberica JRE同梱版。Libericaなのはライセンスまわりの問題という認識。
jre/releaseファイルを確認したところJavaのバージョンは21だったので、参考にする場合はこのページのJVMオプションの説明が当てはまらない部分がある点だけ注意してください。
採用したJVMオプションについて
上の記事からの一番大きな更新点。
2025年現在、Shenandoah GCではなくZGCが第一選択肢となっていそうな雰囲気があります。どちらも正式版になったのはJava 15で同時期ですが、ZGCの性能が上がってきたとかそんな感じっぽい。
以下採用オプション説明。
-Xms4g -Xmx4g
起動時ヒープメモリ、最大ヒープメモリ。指定するなら同じ方がよさげ。実際の利用量の測定とかは他の方がやってくれてると思いますので好きなように設定してください。
-XX:+UseZGC
ZGCを使う。
-XX:+AlwaysPreTouch
起動時に、全てのヒープにアクセスしに行く。起動は遅くなるがXms, Xmxで指定した物理メモリを即座に確保するので実行中のページフォールトによる遅延がなくなる。
-XX:+UseLargePages
メモリ利用時にラージページを利用する。TLBキャッシュの利用エントリ数が減ってメモリアクセスが速くなる。
自分は特に何もせずに有効化できたが、Homeエディションだとこれを許可する設定画面にアクセスできないらしい。ダメだったら諦めましょう。ログ出力して以下みたいなのが出てたらOK。
[0.006s][info][gc,init] Large Page Support: Enabled (Explicit)
また、Large PageとPre Touchを併用すると起動に失敗することがある。ざっと調べた感じ、常駐ソフトなどのせいでメモリが断片化していて連続領域を確保できないせいと思われる(参考)。
自分はBMSプレイ時にブラウザなどほとんどのソフトを切るので困っていないが、配信などをする方はヒープサイズを小さくするかAlwaysPreTouch・UseLargePagesのどちらかを諦めると安定しそう。
-XX:-UsePerfData
パフォーマンス監視機能を無効にする。ほとんど誤差と思われるが切っておいて損はなさそう。
削除・非採用にしたJVMオプションについて
簡潔に。
-XX:+UseShenandoahGC | ZGC使うから消す。 |
-XX:+ExplicitGCInvokesConcurrent | Shenandoah GCだと意味あったっぽいけどZGCだと挙動に変化ないっぽい。 |
-XX:+TieredCompilation | デフォルト有効なので不要。 |
-XX:+UseNUMA | サーバーならともかく個人用PCでNUMAのことって考える必要あるんですか? |
-XX:+UseThreadPriorities | Windowsではプロセス優先度を/abovenormalで上げておけば十分っぽく、スレッド優先度を細かく指定しても意味ない、らしい。 |
-XX:+ShowCodeDetailsInExceptionMessages | デフォルト有効なので不要。 |
-XX:+ZGenerational | JDK 21, 22の場合は有効にすると世代別ZGCになる。JDK 23以降はデフォルト有効。 |
-XX:-ZUncommit | 未使用ヒープメモリをOSに返却する機能を無効化する。Xms = Xmxの場合は勝手に無効になるので不要。 |
世代別ZGC(Generational ZGC):こっちの方が性能がいい(適当説明)。この辺を参考にしてください。
検証
VMMapとかで確認したところ設定どおりにZGCが動いていそう。
GCについて、次のオプションでGCのログを取った:-Xlog:gc*,gc+heap=info,gc+age=trace:file=gc.log:time,uptime,level,tags
統計部分を一部抜粋。
[2025-12-25T04:49:16.322+0900][358.829s][info][gc,stats ] === Garbage Collection Statistics =======================================================================================================================
[2025-12-25T04:49:16.322+0900][358.829s][info][gc,stats ] Last 10s Last 10m Last 10h Total
[2025-12-25T04:49:16.322+0900][358.829s][info][gc,stats ] Avg / Max Avg / Max Avg / Max Avg / Max
...
[2025-12-25T04:49:16.322+0900][358.829s][info][gc,stats ] Old Pause: Pause Mark End 0.000 / 0.000 0.009 / 0.011 0.009 / 0.011 0.009 / 0.011 ms
[2025-12-25T04:49:16.322+0900][358.829s][info][gc,stats ] Old Pause: Pause Relocate Start 0.000 / 0.000 0.008 / 0.012 0.008 / 0.012 0.008 / 0.012 ms
...
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,stats ] Young Pause: Pause Mark End 0.000 / 0.000 0.009 / 0.015 0.009 / 0.015 0.009 / 0.015 ms
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,stats ] Young Pause: Pause Mark Start 0.000 / 0.000 0.008 / 0.009 0.008 / 0.009 0.008 / 0.009 ms
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,stats ] Young Pause: Pause Mark Start (Major) 0.000 / 0.000 0.012 / 0.027 0.012 / 0.027 0.012 / 0.027 ms
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,stats ] Young Pause: Pause Relocate Start 0.000 / 0.000 0.007 / 0.020 0.007 / 0.020 0.007 / 0.020 ms
...
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,stats ] =========================================================================================================================================================
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,exit ] Heap
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,exit ] ZHeap used 424M, capacity 4096M, max capacity 4096M
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,exit ] Cache 3672M (1)
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,exit ] size classes 2G (1)
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,exit ] Metaspace used 51866K, committed 52608K, reserved 1114112K
[2025-12-25T04:49:16.323+0900][358.830s][info][gc,exit ] class space used 6223K, committed 6592K, reserved 1048576K
最大停止時間が 0.027 msとほぼ影響ない値。しかもその停止も楽曲プレイ終了後のみ。プレイ終了後に明示的にSystem.gc()を呼んでいるっぽいので、もしかしたらそんなにガチガチにチューニングする必要はないのかも。曲中にGCが走らないようにすれば十分。
あとこのログは2プレイほどしたあと終了したときの集計だけど、やっぱりヒープサイズは4GBもいらなそうな雰囲気がある。曲とかBGA次第で変わってくる可能性もあるけど。
参考
https://twitter.com/sack_magiclight/status/1826553113719046504:この記事を書くきっかけになったツイート
ざっくりわかった気になるモダンGC入門:Shenandoah GC、ZGCの説明。わかりやすい。2018年の記事なので対応状況などの記述が古いことに注意
ZGC | OpenJDK Wiki:あんまり真面目には読んでないけどZGCのオプションなどについて説明されているWiki
Adopting ZGC in HBase for LINE Messaging:チューニング例。ゲーム用ではなくデータベースシステムの設定であることに注意
宣伝
ワシの差分を遊んでくれ~い
https://bms.congenial-spirits.com/