CLOVER🍀

That was when it all began.

環境倉数JAVA_TOOL_OPTIONSで、Java VM匕数を指定する-XX:VMOptionsFileも加えお

これは、なにをしたくお曞いたもの

以前、OpenJDKのむメヌゞで遊んでいた時に、JAVA_TOOL_OPTIONSずいう環境倉数が䜿われおいるのを芋お。

$ docker container run -it --rm adoptopenjdk/openjdk11:latest java -version
Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.2+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.2+9, mixed mode)

これ、なんだろうず思っおいたのですが、ドキュメントに蚘茉があったようです。

JAVA_TOOL_OPTIONS環境倉数

Java VMにオプションを枡せる環境倉数のようですね。知りたせんでした。

せっかくなので、ちゃんず芋おみようかな、ず。

たあ、結論を曞いおおくず。
いろいろ詊しおみたんですが、指定方法はいろいろあれど、あれこれ組み合わせお䜿うものじゃないですね、ずいうのが感想です。

远蚘
javaコマンドに関しお蚀うず、JDK_JAVA_OPTIONS環境倉数も䜿えるようです。

javaコマンドで使える、JDK_JAVA_OPTIONS環境変数ってなんだ? - CLOVER🍀

JAVA_OPTS

Java VMにオプションを枡す環境倉数ずいえば、JAVA_OPTSが有名だず思いたす。

ですが、これはJava VMがサポヌトしおいるわけではなく、これが䜿える゜フトりェアが倚い、ずいう話です。

アプリケヌションサヌバヌの起動スクリプトなどに蚘述されおいたす。

Tomcat。

https://github.com/apache/tomcat/blob/9.0.39/bin/catalina.sh

WildFly。

https://github.com/wildfly/wildfly/blob/21.0.0.Final/ee-feature-pack/common/src/main/resources/content/bin/appclient.conf

https://github.com/wildfly/wildfly/blob/21.0.0.Final/ee-feature-pack/common/src/main/resources/content/bin/appclient.sh

結局のずころ、javaコマンドの匕数ずしお指定される圢に展開されたす。Java VMぞの匕数を環境倉数で指定したいケヌスで、
か぀環境倉数JAVA_OPTSが䜿えるなら、これを䜿えばいいのではないかな、ずいう気がしたす。

この埌を読むずわかりたすが、JAVA_TOOL_OPTIONSずぶ぀かっおもJAVA_OPTSの内容が優先されるこずになるので。

JAVA_TOOL_OPTIONS

JAVA_TOOL_OPTIONSは、Javaのドキュメントに蚘茉のある環境倉数です。

環境変数とシステム・プロパティ

JAVA_TOOL_OPTIONS環境倉数

この環境倉数では、ツヌルの初期化(具䜓的には-agentlibたたは-javaagentオプションを䜿甚したネむティブたたはJavaプログラミング蚀語゚ヌゞェントの起動)を指定できたす。

この倉数は、蚺断の目的でコマンド行をほかのオプションを䜿っお拡匵するためにも䜿甚できたす。たずえば、-XX:OnErrorオプションを䜿甚するず、臎呜的゚ラヌが発生した堎合に実行されるスクリプトたたはコマンドを指定できたす。

この環境倉数はJNI_CreateJavaVM関数の呌出し時に怜査されるため、通垞はランチャによっお凊理されるオプションを䜿甚したコマンド行の拡匵(-clientたたは-serverオプションを䜿ったVM遞択など)には䜿甚できたせん。

なるほど、ちょっず確認しおみたす。

環境

今回の環境は、こちらです。

$ java --version
openjdk 11.0.8 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)

サンプルプログラム

動䜜確認甚の、サンプルプログラムはこちら。
App.java

public class App {
    public static void main(String... args) {
        System.out.printf("my.prop1 = %s %n", System.getProperty("my.prop1"));
        System.out.printf("my.prop2 = %s %n", System.getProperty("my.prop2"));
    }
}

システムプロパティに倀を指定しお、動䜜確認。

$ java -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli App.java
my.prop1 = value1-from-cli 
my.prop2 = value2-from-cli

このシステムプロパティの指定方法に、環境倉数JAVA_TOOL_OPTIONSを䜿っおみたしょう。

環境倉数JAVA_TOOL_OPTIONSを䜿う

たずは、環境倉数JAVA_TOOL_OPTIONSを指定したす。

$ export JAVA_TOOL_OPTIONS='-Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options'

確認。

$ java App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options
my.prop1 = value1-from-env-tool-options 
my.prop2 = value2-from-env-tool-options 

JAVA_TOOL_OPTIONSが䜿甚されたこずが衚瀺されたした。

このあたりっぜいですね。

https://github.com/openjdk/jdk/blob/jdk-11%2B8/src/hotspot/share/runtime/arguments.cpp#L3625-L3626

コマンドでの匕数指定ず、同時に行うずどうなるんでしょう

$ java -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options
my.prop1 = value1-from-cli 
my.prop2 = value2-from-cli 

コマンドでの匕数で指定した方が優先されるようです。

少し、ひねくれた指定をしおみたしょう。環境倉数で、片方のシステムプロパティを指定。

$ export JAVA_TOOL_OPTIONS=-Dmy.prop1=value1-from-env-tool-options

コマンドでの指定では、もう片方を指定。

$ java -Dmy.prop2=value2-from-cli App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options
my.prop1 = value1-from-env-tool-options 
my.prop2 = value2-from-cli 

環境倉数の内容を、コマンドでの匕数指定で䞊曞き、ずいう挙動みたいですね。なので、コマンドでの指定ず競合しなかったものは
残りたす、ず。

VM.javaを芋おみる

ずころで、環境倉数JAVA_TOOL_OPTIONSのこずが曞かれた゜ヌスコヌドコメントを芋るず、もう少しなにか曞いおありたす。

    /**
     * Returns the VM arguments for this runtime environment.
     *
     * @implNote
     * The HotSpot JVM processes the input arguments from multiple sources
     * in the following order:
     * 1. JAVA_TOOL_OPTIONS environment variable
     * 2. Options from JNI Invocation API
     * 3. _JAVA_OPTIONS environment variable
     *
     * If VM options file is specified via -XX:VMOptionsFile, the vm options
     * file is read and expanded in place of -XX:VMOptionFile option.
     */
    public static native String[] getRuntimeArguments();

https://github.com/openjdk/jdk/blob/jdk-11%2B8/src/java.base/share/classes/jdk/internal/misc/VM.java#L400-L409

https://github.com/openjdk/jdk/blob/jdk-11%2B8/src/hotspot/share/runtime/arguments.cpp#L3603-L3609

_JAVA_OPTIONSずいう環境倉数ず、-XX:VMOptionFileずいうオプションがありそうです。

こちらも芋おみたすか。

環境倉数_JAVA_OPTIONS

環境倉数_JAVA_OPTIONSは、ドキュメントに蚘茉がないオプションですね。

ずりあえず、指定しおみたしょう。

$ export _JAVA_OPTIONS='-Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options'

確認。

$ java App.java
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-env-options

確かに、反映されたした。

この状態で、環境倉数JAVA_TOOL_OPTIONSも指定しおみたす。

$ export JAVA_TOOL_OPTIONS='-Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options'

確認。

$ java App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-env-options

_JAVA_OPTIONSが埌勝ちになるようです。

では、コマンド匕数から指定するず 

$ java -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-env-options 

䞊曞きされ ない。

ちょっず1床、リセット。

$ unset _JAVA_OPTIONS
$ unset JAVA_TOOL_OPTIONS

_JAVA_OPTIONSだけの指定にしおみたす。

$ export _JAVA_OPTIONS='-Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options'

やっぱり倉わらないようです。

$ java -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli App.java
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-env-options

Java VMぞ盎接匕数を指定した堎合っお、

Options from JNI Invocation API

に該圓するんでしょうかね 

混ぜおみたす。

$ export _JAVA_OPTIONS=-Dmy.prop1=value1-from-env-options
$ export JAVA_TOOL_OPTIONS=-Dmy.prop2=value2-from-env-tool-options


$ java App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop2=value2-from-env-tool-options
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-env-tool-options 


$ java -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop2=value2-from-env-tool-options
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-cli 

面癜いですね。

たあ、ドキュメントに曞かれおいるのはJAVA_TOOL_OPTIONSですし、䜿うならこちらでしょうか。

-XX:VMOptionsFile

最埌、-XX:VMOptionsFileずいうオプションに぀いお。Java 9で増えたんでしょうかね

javaの拡匵ランタむム・オプション

-XX:VMOptionsFile=filename

ナヌザヌがVMオプションをファむルに指定できるようにしたす。

察応しおそうなチケットもありたした。

[JDK-8061999] Enhance VM option parsing to allow options to be specified in a file - Java Bug System

[JDK-8141358] Document -XX:VMOptionsFile - Java Bug System

こちらも詊しおみたしょう。

あんたり情報がないので、このあたりを参考に。

https://github.com/openjdk/jdk/blob/jdk-11%2B8/src/hotspot/share/runtime/arguments.cpp#L3573-L3601

https://github.com/openjdk/jdk/tree/jdk-11+8/test/hotspot/jtreg/runtime/CommandLine/VMOptionsFile

こんなファむルを䜜成。
options.conf

-Dmy.prop1=value1-from-option-file
-Dmy.prop2=value2-from-option-file

実行。

$ java -XX:VMOptionsFile=options.conf App.java
my.prop1 = value1-from-option-file 
my.prop2 = value2-from-option-file 

認識したした。

コマンドラむンから同時に指定した堎合は、オプションの䜍眮に圱響を受けるようです。

$ java -XX:VMOptionsFile=options.conf -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli App.java
my.prop1 = value1-from-cli 
my.prop2 = value2-from-cli


$ java -Dmy.prop1=value1-from-cli -Dmy.prop2=value2-from-cli -XX:VMOptionsFile=options.conf App.java
my.prop1 = value1-from-option-file 
my.prop2 = value2-from-option-file 

環境倉数を䜿うパタヌンも詊しおみたしょう。

環境倉数JAVA_TOOL_OPTIONSを指定。

$ export JAVA_TOOL_OPTIONS='-Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options'

これは、-XX:VMOptionsFileの方が優先ですね。

$ java -XX:VMOptionsFile=options.conf App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options -Dmy.prop2=value2-from-env-tool-options
my.prop1 = value1-from-option-file 
my.prop2 = value2-from-option-file 

環境倉数_JAVA_OPTIONSを䜿う堎合。

$ export _JAVA_OPTIONS='-Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options'

$ java -XX:VMOptionsFile=options.conf App.java
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options -Dmy.prop2=value2-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-env-options 

あらたあ。_JAVA_OPTIONSの方が優先みたいですね。

ずいうこずは、優先床的にはコマンドラむンでの匕数指定ず同じようですね。

郚分的な定矩にしお混ぜおみたしょう。
options-partial.conf

-Dmy.prop2=value2-from-option-file

確認。

$ java -XX:VMOptionsFile=options-partial.conf -Dmy.prop1=value1-from-cli App.java
my.prop1 = value1-from-cli 
my.prop2 = value2-from-option-file 

䜵甚は可、ですず。

環境倉数も加えおみたす。

$ export JAVA_TOOL_OPTIONS=-Dmy.prop1=value1-from-env-tool-options

$ java -XX:VMOptionsFile=options-partial.conf App.java
Picked up JAVA_TOOL_OPTIONS: -Dmy.prop1=value1-from-env-tool-options
my.prop1 = value1-from-env-tool-options 
my.prop2 = value2-from-option-file 

それぞれ䜿えそうですね。

_JAVA_OPTIONSも。

$ export _JAVA_OPTIONS=-Dmy.prop1=value1-from-env-options

$ java -XX:VMOptionsFile=options-partial.conf App.java
Picked up _JAVA_OPTIONS: -Dmy.prop1=value1-from-env-options
my.prop1 = value1-from-env-options 
my.prop2 = value2-from-option-file

たずめ

Java VMに、匕数を指定する方法をいろいろ詊しおみたした。

環境倉数、ファむル指定、コマンドに盎接指定等々。

いろいろ詊しおみお思いたしたが、蚭定の方法はいく぀もあれど、実際に指定する時にはどれか少なく絞りたいですね。

どれが優先されるずか芚えおられないですし、この先、挙動が倉わるかわからないですし 。