メインコンテンツまでスキップ

「Javaの鉱脈」でJVMオプションの記事を書きました

Sato Taichi

WEB+DB PRESS の Vol.82 に、かなり気合いの入った JVM オプションの記事を書いたので、是非読んで頂きたい。

2014/8/23 発売ですので、既に購入頂いてる方も多いと思います。

電子書籍版もありますので物理的な媒体に興味がない方は PDF を買って下さい。

今回の記事における対象読者について#

今回の記事は、ターゲットとして Java に余り時間をコミットしていないけども便利なので JVM 上で動くアプリケーションをウッカリ運用している人をイメージしながら書きました。

例えば、OSS ものだと Hadoop や ZooKeeper、Lucene や Solr、商用製品だと Stash とか JIRA とか confluence とかそういうものですね。

僕の観測範囲だと、PHP や Perl の様なスクリプト言語から Scala へ移行している人々を見かけますが、そういう人たちは多分きっと負荷テスト中であるとか、アプリケーションのリリース後に謎のパフォーマンス劣化に襲われて無我夢中で Google 先生から得られる情報を元に JVM のオプションをガチャガチャと弄ってるんじゃないかなぁ…と想像しています。

今回の記事は、そういった時に調査の足がかりとなるような知識になればイイなぁと考えています。

前半部分では JVM のメモリモデルの話と GC のアルゴリズムの話。それだけだと実効性に乏しいので後半部分では具体的な値を伴うオプションの話を書いています。

特に GC のアルゴリズムを説明するにあたって、GC ログにでるメッセージを読めるようにキーワードとなる単語をあえて和訳せずに書きました。興味をもったら公式のブログにおける GC ログの話も読んで下さい。

これでも内容的には不足がある実務者の皆様は、公式のチューニングガイドが昨日リリースされましたのでじっくり読むと良いでしょう。

書籍になっており、かつより読み易いガイドとしてはJava Performance: The Definitive Guideをお勧めします。

-XX:+UseLargePages については書くかどうか迷いましたが、動作検証が間に合わなかったので書きませんでした。6GB 以上のメモリを JVM に割り当てて運用している皆様は是非お試し下さい。OS 側の設定がいくつか必要なので若干面倒なのですが…。

JVM のオプションを一覧化するツールについて#

今回の記事は、当初重要なオプションの変更や追加、廃止にもっとフォーカスした記事にしようとしていたので、オプションを一覧化するツールを作りました。

このツールは OpenJDK のソースコードリポジトリからコードをダウンロードした上で、C++のコードを正規表現を駆使して解析します。このツールで作ったデータはcompare JVM optionsにて公開しています。

表の見方は何となく分かるとは思いますが一応説明しておきます。

  • name

    • オプションを設定する際に利用する名前です
  • description

    • 当該オプションの説明です
  • type

    • どんな範囲の値を当該オプションに設定できるのか決めるオプションの型です。C++の型ですが、何となく類推して下さい。
  • 6,7,8

    • JVM の各バージョンで当該オプションがサポートされているなら o 。サポートされていないなら x です。
  • 6.default,7.default,8.default

    • JVM の各バージョンにおける当該オプションの静的に決まるデフォルト値です。

    • 実行環境や他のオプションとの兼ね合いで決まる値もあります。

    • hotspot/file/src/share/vm/runtime/arguments.cpp辺りを読むとエルゴノミクスによって決まる値をある程度類推できます。

  • kind

    • オプションがどのような状況で使えるのかを表す種類です。 notproductdevelop のオプションはリリースバイナリには含まれていません。
  • file

    • オプションが定義されていたファイル名です。

    • オプションが定義されていた場所によって、どのような目的のオプションなのかある程度類推できます。

    • 例えば、share/vm/gc_implementation/g1/g1_globals.hpp なら G1GC 用のオプションです。

このツールに関する雑感#

JVM はプロダクションビルド以外で、-XX:+PrintFlagsWithComments を付けて起動するとオプションの一覧が説明付きで標準出力されるのですけども、これだとプラットフォーム依存性のあるオプションが全部は出てこないのですよね。

JVM のオプションは公式にメンテナンスされている一覧が存在しないし、一覧を探して出てくる情報がどれもこれも古い上に、どうやって作ったのか分からない代物ばかりなので自分で作りました。

最初は手元にあった Java8 のソースコードだけをパーズしていたので、コードを自動でダウンロードしてはいなかったのですけども、Java6 と Java7 との差分が欲しくなったりだとか、特定バージョンのコードが欲しくなったりだとかを繰り返しているうちに自動でダウンロードしないと話にならん感じがしたので Gradle でダウンロードするようにしました。

java.net のリポジトリの負荷が高いのは、こういうアクセスも結構あるせいなんじゃないかなぁ…とか思っています。

JSON が出力できるのですけども、これは当初解析したオプションをこねくり回すのを手元にある JSON ベースのドキュメントデータベースでやっていたからです。Google Spreadsheet にインポートする為に CSV 形式で出力するようにしました。

コードベースとしては RxJava と Stream API が混ざってて気持ち悪い感じになっていますが、これはコードを書いた時期が随分ズレていたからです。どちらかに統一しようと思えば出来なくは無いと思いますが、雑に書いたツールなので、これ以上あまり頑張れません、PR 頂ければマージします。