-XX:+DisableExplicitGCに関するJDK7とJDK8の違い
この記事は JVM Advent Calendar 2014の12/5分の記事*1です。昨日は
@jyukutyoさんのJITWatchでJITコンパイルを見よう!でした。
HotSpotには-XX:+DisableExplicitGC
というオプションがありますが、この挙動がJDK8のリリースから変わっていたのでまとめます。
-XX:+DisableExplicitGC とは
System.gc()
でGCリクエストされても無視するオプションです。アプリケーション中でSystem.gc()
を実行されるとメジャーGCが発生します。HotSpotに任せた場合はマイナーGCで十分回収できたかもしれないので、アプリケーションでSystem.gc()を呼び出すのはあまり好ましいことではありません。
無視するといっても内部的にそんな難しいことは行われておらず、OpenJDK8のソースを見るとif文でオプションが有効だったらGCしないだけです。
jdk8u/hotspot/src/share/vm/prims/jvm.cpp
451 JVM_ENTRY_NO_ENV(void, JVM_GC(void)) 452 JVMWrapper("JVM_GC"); 453 if (!DisableExplicitGC) { 454 Universe::heap()->collect(GCCause::_java_lang_system_gc); 455 } 456 JVM_END
JDK8よりjcmd <pid> GC.runに対しても有効になる
JDK7までは -XX:+DisableExplicitGC
が有効化されていても、jcmd GC.runでGCリクエストが受け付けられていたのですが、JDK8より以下のメッセージ『Explicit GC is disabled, no GC has been performed.』が返ってきてGCは動きません。
$ jcmd 18952 GC.run 18952: Explicit GC is disabled, no GC has been performed.
ソースを見ると、JDK8よりDisableExplicitGCフラグのチェックがjcmd <pid> GC.runの実装に追加されています。
jdk8u/hotspot/src/share/vm/services/diagnosticCommand.cpp
258 void SystemGCDCmd::execute(DCmdSource source, TRAPS) { 259 if (!DisableExplicitGC) { 260 Universe::heap()->collect(GCCause::_java_lang_system_gc); 261 } else { 262 output()->print_cr("Explicit GC is disabled, no GC has been performed."); 263 } 264 }
この修正による影響を受けるシステム
例えば、以下のようなシステムで影響を受けると思います。
まとめ
- JDK8より起動オプション
-XX:+DisableExplicitGC
有効時にはjcmd <pid> GC.run
は無視されます jcmd <pid> GC.class_histogram
によってメジャーGCのリクエストをすることは可能です
*1:ええ、申し込んだのは2015/1/7ですがせっかく空いてたので