⇧ X(旧:Twitter)で話題になってたけど、研究が続いていたんですな、餃子が食べたくなりますな。
JavaのJVMのオプションの設定が分かり辛いが、明示的に設定しないとデフォルト値が使われる模様
Javaのアプリケーションを起動する際に、「Java仮想マシン(JVM:Java Virtual Machine )」のオプションを設定することができるのですが、設定した「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの値をリセットするにはどうしたら良いのかを知りたかったんだけど、見事にドキュメントに記載が無い...
流石は、Oracleさん、安定の不親切さ...
で、致し方ないから、実際に動かしてみて検証してみたところ、「Java仮想マシン(JVM:Java Virtual Machine )」が終了した段階で、設定した「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの値も棄却されるらしい。
つまり、「Java仮想マシン(JVM:Java Virtual Machine )」のインスタンス毎にオプションの設定がなされるのだと。
なので、アプリケーションサーバーなんかで稼働してるJavaアプリケーションに紐づく「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定を変更したい場合は、再起動が必要ということらしい。(「Java仮想マシン(JVM:Java Virtual Machine )」のインスタンスを生成し直すってことになるんかな?)
で、例の如く、
⇧ 上記の記事の時の環境で、試してみました。
■/home/ts0818/work/test_jvm_option/execute_jstat.sh
#!/bin/bash ## ■■■■■■■■■■■■■■■ ## ■ 変数定義 ## ■■■■■■■■■■■■■■■ jstat_TestJvmOption_tsv="jstat.tsv" #jvm_start_option_Xmx1024m="-Xmx1024m" jvm_start_option_Xmx2048m="-Xmx2048m" jvm_start_option_PrintFlagsFinal="-XX:+PrintFlagsFinal" interval_millsecond=100 limit_display_result_row_count=20000 datetime_format="%Y/%m/%d %H:%M:%S.%3N" jvm_java_version="-version" result_log="result.log" ## ■■■■■■■■■■■■■■■ ## ■ ファイル初期化 ## ■■■■■■■■■■■■■■■ if [ -e ${jstat_TestJvmOption_tsv} ]; then rm ${jstat_TestJvmOption_tsv} && touch ${jstat_TestJvmOption_tsv} else touch ${jstat_TestJvmOption_tsv} fi ## ■■■■■■■■■■■■■■■ ## ■ Java実行 ## ■■■■■■■■■■■■■■■ # JVMのバージョンを確認 #execute_java_version=$(java ${jvm_java_version}) java ${jvm_java_version} 2>> ${result_log} && # JVM起動時の設定を確認(Xmxの設定のみ表示) jvm_setting_output=$(java ${jvm_start_option_Xmx2048m} ${jvm_start_option_PrintFlagsFinal} 2>&1 | grep -Ei "MaxHeapSize") echo "${jvm_setting_output}" >> ${result_log} && # TestJvmOptionクラスの実行 class_TestJvmOption="TestJvmOption" jvm_start_option_flight_recorder="-XX:StartFlightRecording=dumponexit=true,filename=" output_jfr_TestJvmOption=TestJvmOption_flight_recording_$(date +"%Y-%m-%d_%H-%M-%S").jfr #java ${jvm_start_option_Xmx2048m} ${class_TestJvmOption} $1 >> ${result_log} & java ${jvm_start_option_flight_recorder}${output_jfr_TestJvmOption},name=${class_TestJvmOption} ${jvm_start_option_Xmx2048m} ${class_TestJvmOption} $1 >> ${result_log} & #jps -lm | grep TestJvmOption | awk '{print $1}' | xargs -I{} jstat -gcutil {} ${interval_millsecond} ${limit_display_result_row_count} | awk -F, '{print strftime(`${datetime_format}`,systime()) $1}' >> ${jstat_TestJvmOption_tsv} #jps -lm | grep TestJvmOption | awk '{print $1}' | xargs -I{} jstat -gc {} ${interval_millsecond} ${limit_display_result_row_count} | awk -F, '{print strftime("%(${datetime_format})",systime()) $1}' >> ${jstat_TestJvmOption_tsv} #jps -lm | grep TestJvmOption | awk '{print $1}' | xargs -I{} jstat -gc {} ${interval_millsecond} ${limit_display_result_row_count} | awk -v datetime_format="${datetime_format}" -F, '{print strftime(datetime_format, systime()) $1}' >> ${jstat_TestJvmOption_tsv} # heap dump fileを取得する jps | grep TestJvmOption | awk '{print $1}' | xargs -I{} jmap -dump:format=b,file=./TestJvmOption_heapdump.hprof {} & # jstatコマンドの出力をファイルに追記(ヘッダー行を含む) #jstat -gc $(jps | grep TestJvmOption | awk '{print $1}') ${interval_millsecond} ${limit_display_result_row_count} | jps | grep TestJvmOption | awk '{print $1}' | xargs -I{} jstat -gc {} ${interval_millsecond} ${limit_display_result_row_count} | awk -v datetime_format="${datetime_format}" 'BEGIN { OFS="\t" } { split($1, arr, " "); ms = sprintf("%.3f", arr[1] / 1000); # ミリ秒を秒に変換し、小数点以下3桁までの文字列にフォーマット cmd = "date +\"" datetime_format "\""; # 日時フォーマットを含むdateコマンドを生成 cmd | getline formatted_date; # dateコマンドを実行してフォーマットされた日時を取得 close(cmd); # 各列をタブ区切りで結合 output = formatted_date "." ms; for (i = 1; i <= NF; i++) { output = output "\t" $i; } print output; }' >> ${jstat_TestJvmOption_tsv} # -Xmx2048mのJVMオプションを設定して起動 jvm_option_status_with_setting=$(java ${jvm_start_option_Xmx2048m} ${jvm_start_option_PrintFlagsFinal} 2>&1) echo "${jvm_option_status_with_setting}" > jvm_option_status_with_setting.log # JVMオプションを何も設定せずに起動 jvm_option_status_without_setting=$(java ${jvm_start_option_PrintFlagsFinal} 2>&1) echo "${jvm_option_status_without_setting}" > jvm_option_status_without_setting.log #java ${jvm_start_option_PrintFlagsFinal} ${jvm_start_option_Xmx} TestJvmOption $1 >> result.log & #while jps | grep -q TestJvmOption; #do # jstat -gc $(jps | grep TestJvmOption | awk '{print $1}') 100 20000 >> jstat.log; #done #until jps | grep TestJvmOption # do # #echo "start jstat TestJvmOption" # jstat -gc $(jps | grep TestJvmOption | awk '{print $1}') 100 20000 >> ${jstat_TestJvmOption_tsv} # done #until jps | grep -q TestJvmOption # do # jstat -gc $(jps | grep TestJvmOption | awk '{print $1}') 100 20000 | awk -F, '{print strftime("%Y/%m/%d %H:%M:%S",systime()) $1}' >> ${jstat_TestJvmOption_tsv} # done #until jps | grep -q TestJvmOption # do # jstat -gc $(jps | grep TestJvmOption | awk '{print $1}') 100 20000 | perl -wn -e '$d = `date "+%Y/%m/%d %H:%M:%S"`; chomp $d; print "$d | $_"' >> ${jstat_TestJvmOption_tsv} # done #jstat -gc $(jps | grep TestJvmOption | awk '{print $1}') 100 20000 | awk -F, '{print strftime("%Y/%m/%d %H:%M:%S",systime()) $1}';
⇧ のシェルスクリプトのファイルを実行すると、
⇧ JVMオプションを設定した場合と、設定しなかった場合のログが出力されるので、中身を見てみると
「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定ありで起動のログ抜粋
[Global flags] intx ActiveProcessorCount = -1 {product} uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product} ...省略 bool ManagementServer = false {product} uintx MarkStackSize = 4194304 {product} uintx MarkStackSizeMax = 536870912 {product} uintx MarkSweepAlwaysCompactCount = 4 {product} uintx MarkSweepDeadRatio = 1 {product} intx MaxBCEAEstimateLevel = 5 {product} intx MaxBCEAEstimateSize = 150 {product} uintx MaxDirectMemorySize = 0 {product} bool MaxFDLimit = true {product} uintx MaxGCMinorPauseMillis = 18446744073709551615 {product} uintx MaxGCPauseMillis = 18446744073709551615 {product} uintx MaxHeapFreeRatio = 100 {manageable} uintx MaxHeapSize := 2147483648 {product} intx MaxInlineLevel = 9 {product} intx MaxInlineSize = 35 {product} ...省略 intx hashCode = 5 {product}
「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定なしで起動のログ抜粋
[Global flags] intx ActiveProcessorCount = -1 {product} uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product} ...省略 bool ManagementServer = false {product} uintx MarkStackSize = 4194304 {product} uintx MarkStackSizeMax = 536870912 {product} uintx MarkSweepAlwaysCompactCount = 4 {product} uintx MarkSweepDeadRatio = 1 {product} intx MaxBCEAEstimateLevel = 5 {product} intx MaxBCEAEstimateSize = 150 {product} uintx MaxDirectMemorySize = 0 {product} bool MaxFDLimit = true {product} uintx MaxGCMinorPauseMillis = 18446744073709551615 {product} uintx MaxGCPauseMillis = 18446744073709551615 {product} uintx MaxHeapFreeRatio = 100 {manageable} uintx MaxHeapSize := 1027604480 {product} intx MaxInlineLevel = 9 {product} intx MaxInlineSize = 35 {product} ...省略 intx hashCode = 5 {product}
⇧ と、「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定で、明示的に設定した項目(今回は、XX:Xmx)だけ異なっていることから、オプションの設定は明示的に設定しない場合は常にデフォルトの設定値が利用されてるようです。
Server JVM Default Initial and Maximum Heap Sizes
The default initial and maximum heap sizes work similarly on the server JVM as it does on the client JVM, except that the default values can go higher. On 32-bit JVMs, the default maximum heap size can be up to 1 GB if there is 4 GB or more of physical memory. On 64-bit JVMs, the default maximum heap size can be up to 32 GB if there is 128 GB or more of physical memory. You can always set a higher or lower initial and maximum heap by specifying those values directly; see the next section.
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/parallel.html#default_heap_size
⇧「WSL 2(Windows Subsystem for Linux 2)」のUbuntuで稼働する場合の「Java仮想マシン(JVM:Java Virtual Machine )」がどういう扱いになるのかが分からんのだけど、一応、ホスト側(Windows 10 Home)のメモリは8GBなんだけど、そもそも64bitのJVMが128GB以上の説明しかないから、何とも言えんのだけど、自分の環境では、
⇧ 64bitの「Java仮想マシン(JVM:Java Virtual Machine )」ということらしいのだけど、
が、Xmxのデフォルト値らしいので、概ね、1GB程度ってことになるんかね、う~む、どういう計算式で算出されてるかが分からんが...
というわけで、「Java仮想マシン(JVM:Java Virtual Machine )」の設定は、「Java仮想マシン(JVM:Java Virtual Machine )」のインスタンス毎に有効になるようなので、Javaアプリケーションを稼働させる時に起動する「Java仮想マシン(JVM:Java Virtual Machine )」毎に考えれば良いようです。
つまり、何かしらデフォルト以外の設定にしたい場合は「Java仮想マシン(JVM:Java Virtual Machine )」を起動し直す際に、明示的に設定してあげる必要がありそうです。
逆に言うと、起動時にしか「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定は、設定できないということなんかね?
「Java仮想マシン(JVM:Java Virtual Machine )」もオブジェクト指向になっているってことですかな。
イメージ的には、
⇧ みたいな感じで、javaコマンドの実行時にオプションの設定ありだった場合に、「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定のデフォルト値を上書きして「Java仮想マシン(JVM:Java Virtual Machine )」のインスタンスを生成・起動するってことなんでしょうね、たぶん。
ちなみに、ドキュメントを見た限りでは、「Java仮想マシン(JVM:Java Virtual Machine )」のオプションは、
■Java 8
The java
command supports a wide range of options that can be divided into the following categories:
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
■Java 11
Overview of Java Options
The java
command supports a wide range of options in the following categories:
-
Standard Options for Java: Options guaranteed to be supported by all implementations of the Java Virtual Machine (JVM). They’re used for common actions, such as checking the version of the JRE, setting the class path, enabling verbose output, and so on.
-
Extra Options for Java: General purpose options that are specific to the Java HotSpot Virtual Machine. They aren’t guaranteed to be supported by all JVM implementations, and are subject to change. These options start with
-X
.
The advanced options aren’t recommended for casual use. These are developer options used for tuning specific areas of the Java HotSpot Virtual Machine operation that often have specific system requirements and may require privileged access to system configuration parameters. Several examples of performance tuning are provided in Performance Tuning Examples. These options aren’t guaranteed to be supported by all JVM implementations and are subject to change. Advanced options start with -XX
.
-
Advanced Runtime Options for Java: Control the runtime behavior of the Java HotSpot VM.
-
Advanced JIT Compiler Options for java: Control the dynamic just-in-time (JIT) compilation performed by the Java HotSpot VM.
-
Advanced Serviceability Options for Java: Enable gathering system information and performing extensive debugging.
-
Advanced Garbage Collection Options for Java: Control how garbage collection (GC) is performed by the Java HotSpot
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
⇧ Javaのバージョンによって変わってくるってことなんかね?
Java 8 | Java 11 |
---|---|
Standard Options | Standard Options for Java |
Non-Standard Options | Extra Options for Java |
Advanced Runtime Options | Advanced Runtime Options for Java |
Advanced JIT Compiler Options | Advanced JIT Compiler Options for java |
Advanced Serviceability Options | Advanced Serviceability Options for Java |
Advanced Garbage Collection Options | Advanced Garbage Collection Options for Java |
⇧ Java 8とJava 11で比較してみたけども、概ね、同じ感じってことになるんかね?
一応、Java 17とJava 21のドキュメントも確認してみたけど、
■Java 17
■Java 21
⇧ Java 11と大枠は変わっていなさそう。
Javaのドキュメントに限らないけど、「MECE(Mutually Exclusive and Collectively Exhaustive)」な感じで整備して欲しいっすな。
たらい回しにする場合は、参照先のリンクを掲載して欲しいんよね...
あとは、内輪だけで通じるような用語を使わないで欲しいよね...
初見の人が把握しやすい内容でお願いしたいところです。
ちなみに、「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定のデフォルト値を恒久的に変更できるのかどうかは分かりませんでした...ドキュメントで明示して欲しいのは、そういうとこだと思うよ...
で、ネットの情報をググっていたら、
⇧ stackoverflowによると、
What I Know:
So far I have found out that:
JAVA_OPTS
is not used by the JDK, but by a bunch of other apps (see this post).JAVA_TOOL_OPTIONS
and_JAVA_OPTIONS
are ways to specify JVM arguments as an environment variable instead of command line parameters.- The are picked up by at least
java
andjavac
- They have this precedence:
_JAVA_OPTIONS
(overwrites the others)- Command line parameters
JAVA_TOOL_OPTIONS
(is overwritten by the others)
- The are picked up by at least
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
⇧ という質問者の記述があって、回答とかも参照すると
の4つの環境変数なるものが出てきてるんだが、環境変数で「Java仮想マシン(JVM:Java Virtual Machine )」のオプションの設定のデフォルト値を恒久的に変更できるってことなんかな?
回答者の記述を見ると、
⇧『The fact that _JAVA_OPTIONS
is not documented suggests that it is not recommended to use this variable, and I've actually seen people abuse it by setting it in their ~/.bashrc
. However, if you want to get to the bottom of this problem, you can check the source of Oracle HotSpot VM (e.g. in OpenJDK7).』で、結局、ソースコードを見ろってことになるのは止めて欲しいんだが...そもそも、「src/share/vm/runtime/arguments.cpp」って、C++とか分からんから...
「_JAVA_OPTIONS
」の使用が非推奨であると判断するに至ったドキュメントを教えて欲しいところですな...
相変わらず、Javaもカオスですな...
何か、新しいJDKのバージョンを出して機能を追加してくれるのも良いんだけど、このあたりのドキュメントの整備の方を先に頑張って欲しい気はする...
まぁ、環境変数は対象外です、って言われてしまったらそれまでなんだけど、Javaに関係する環境変数っぽいから、面倒見て欲しいのだけどね...
何故か、
⇧ トラブルシューティングガイドで「環境変数」が載っているのだけど、
17.3.5 環境変数
環境変数の設定が原因で問題が発生する場合があります。バグ・レポートの作成時に、次のJava環境変数の値(設定されている場合)を記入してください。
-
JAVA_HOME
-
JRE_HOME
-
JAVA_TOOL_OPTIONS
-
_JAVA_OPTIONS
-
CLASSPATH
-
JAVA_COMPILER
-
PATH
-
USERNAME
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/troubleshoot/bugreports003.html#CHDHHHBJ
⇧ どちらにしろ、「JAVA_OPTS」は載っていないし、そもそも、環境変数について項目名だけ羅列されてるだけで、環境変数がどう機能するのかについての説明は無いんだが...
なんだかんだで、不毛な時間を過ごしてしまったではないか...時間を返して欲しい...
毎度モヤモヤ感が半端ない...
今回はこのへんで。