Java 8とJava 11でJAVA_TOOL_OPTIONS環境変数の挙動が異なる

先週の以下の記事で未検証に終わった部分を検証してみた。

kdnakt.hatenablog.com

 

 

[JAVA_TOOL_OPTIONS環境変数とは]

あらためて簡単にまとめておくと……

 

  • Javaアプリケーションのコマンドライン・オプションを拡張できる
  • 環境変数なので、複数のJavaアプリケーションを同一マシン上で動かす場合に共通化できる
  • 具体的には、Javaエージェントの設定を行ったり、エラー発生時のスクリプトを指定したりできる

 

先週まで自分は全く知らなかったのだが、調べてみたところ、いくつかの記事でこの環境変数に言及されていた。

JAVA_TOOL_OPTIONS環境変数でAWS Lambda関数のシステムプロパティを設定する – もばらぶエンジニアブログ

Windowsシステム環境変数でJava-VMオプションを指定する方法 | GWT Center

Java メモリ エラーの回避とデバッグ - CircleCI

Picked up JAVA_TOOL_OPTIONS: を擬似的に消す | 雑記帳

 

[Java 8での挙動]

先週の記事にも書いたが、Java 8では1024文字までという制限があるようだ。

 

AWS LambdaのJava 8ランタイム (OpenJDK 1.8.0_201)で試したところ、JAVA_TOOL_OPTIONSの設定値が最大文字数である1024文字を超えると、環境変数に設定した値がすべて無効になってしまった。

具体的には、JAVA_TOOL_OPTIONS: -Dmykey=myvalue ...(1024文字以上続ける)のようにすると、System.getProperty("mykey")で取得できる値がnullになってしまった。

1024文字以下であれば、myvalueが取得できるので、The variable will be ignored if it exceeds the length of the buffer.というJDKのソースコードのコメント通りの動きをしていることがわかる。

 

[Java 11での挙動]

他方、Java 11で試したところ、Java 8とは異なる結果が得られた。

AWS LambdaのJava 11ランタイム(Amazon Corretto 11.0.8)で先ほどと同じコードを動作させたところ、これまで最大文字数とされていた1024文字を超えても、環境変数に設定した値がすべて利用可能だった。

 

どのバージョンで挙動が変わったのか確かめるべく、OpenJDKのリポジトリを探したところ思いのほか早く結果がわかった。

 

Java 9では既にparse_options_environment_variable関数のバッファサイズ1024の制限がなくなっており、おそらくJava 9の初期からこうなのだろう。変更の意図を調べてみようと思ったが、Google先生に聞いてもうまく答えを得ることはできなかった。

 

[まとめ]

  • Java 8とJava 11でJAVA_TOOL_OPTIONS環境変数の挙動が変わっていた
  • Java 8では最大文字数1024の制限があり、それを超えるとすべての設定値が無効になった
  • Java 11では上記の最大文字数の制限はなくなっていた
  • この変更はJava 9で発生したものらしい
  • サンプルコードは以下のリポジトリにまとめてある