unnamed

Javaとか、http://twitter.com/sugarlife

コアダンプから Java 起動オプションの抜き出し方

この記事は JVM Advent Calendar 2日目 の記事です。

JVM を触っているとコアを吐いて落ちる事がしばしばあります。ええ、しばしばあります。
こういう時にどのようなオプションで起動していたかをうっかり忘れると後々面倒です。
でも、実は簡単に解ります。

簡単なやり方

# strings core.12672 | grep -- -Xmx
-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly -Xmx1500m -Xms1500m -Xloggc:gc.log -XX:+PrintGCDetails -XX:+CMSClassUnloadingEnabled

-Xmxを指定していないときは -XX: とかで grep すると引っ掛かります。

JVM に興味があってちゃんと取りたい人向け

Arguments::_jvm_args_arrayJava 起動オプションを格納した配列で、Arguments::_num_jvm_args がこの配列長(Java 起動オプションの数)です。この静的メンバ変数らはコアダンプが出力された時も存在しています。
なので、gdb で、この配列から要素を引っこ抜いてやれば全 Java 起動オプションが取れます。

たとえば、コアを gdb で起動して以下のコードを実行させれば全 Java 起動オプションが表示されます。

set $num = Arguments::_num_jvm_args
set $i = 0

while($i < $num)
  x/a Arguments::_jvm_args_array + $i
  x/s $__
  set $i++
end

※:バージョンによってはシンボル名が違ったりマングリングされてたりで、Arguments::_num_jvm_args が _ZN9Arguments13_num_jvm_argsE になってたりする場合もあります。

実証 (上のコードを test.gdb として保存しておく)

# java -Xmx100M -Xms100M -XX:+UseConcMarkSweepGC -Xloggc:gc.log -XX:+PrintGCDetails -XX:+CMSClassUnloadingEnabled Test &
[1] 12672
# gcore -o ./core 12672()
Saved corefile ./core.12672
# gdb /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.25.x86_64/jre/bin/java-abrt core.12672 < test.gdb()
gdb-peda$  > > > >
0x7fbd80003120: 0x7fbd80003050
0x7fbd80003050: "-Xmx100M"
0x7fbd80003128: 0x7fbd80003070
0x7fbd80003070: "-Xms100M"
0x7fbd80003130: 0x7fbd80003090
0x7fbd80003090: "-XX:+UseConcMarkSweepGC"
0x7fbd80003138: 0x7fbd80003030
0x7fbd80003030: "-Xloggc:gc.log"
0x7fbd80003140: 0x7fbd80003100
0x7fbd80003100: "-XX:+PrintGCDetails"
0x7fbd80003148: 0x7fbd800030b0
0x7fbd800030b0: "-XX:+CMSClassUnloadingEnabled"
gdb-peda$ quit

おわりに

strings の方が楽でしたね!僕は gdb スクリプト書いてから気付きましたばーかばーか!(つД`)・゚・