Java使用しているWebアプリケーション(Jenkins)が応答しなくなる問題を診断しようとしています。jstack
を-F
フラグなしで実行すると、何もしませんが、フラグを設定してスレッドダンプを強制すると、結果が得られるだけでなく、アプリケーションが応答を開始し、最終的に再び応答を停止するまで何も起こらなかったかのように続行します。
jstack -F
フラグは、実行中のJVMに影響を与え、応答しないアプリケーションが再び応答を開始する原因になりますか?
Jstackのソースを見ることができます here 。 -F引数は、jstackがjvmに接続する方法を変更します。 -F(または-m)を使用すると、JStackはJavaデバッガーインターフェースを使用してjvmに接続します。pidが指定されている場合、JStackは SA PID Attaching Connector と接続しますと言う、
デバッグするプロセスは、デバッグモードで(つまり、-agentlib:jdwpまたは-Xrunjdwpを使用して)開始されている必要はありません。プロセスがhungであっても問題ありません。
なぜ応答しないアプリケーションが再び応答を開始するのかはわかりませんが、上のリンクには、
プロセスは、このコネクタが接続されると中断され、このコネクタが切断されると再開されます。
これが影響する可能性があります。
jstack -F -l pidは次のようになります(作業ディレクトリがJava_HOMEであると想定)
bin/Java -Dsun.jvm.hotspot.debugger.useWindbgDebugger -Dsun.jvm.hotspot.debugger.useProcDebugger -cp lib/sa-jdi.jar;lib/tools.jar Sun.tools.jstack.JStack -F -l pid
そして Sun.tools.jstack.JStack code
if (arg.equals("-F")) {
useSA = true;
}
.....
// now execute using the SA JStack tool or the built-in thread dumper
if (useSA) {
// parameters (<pid> or <exe> <core>
...
runJStackTool(mixed, locks, params);
} else {
// pass -l to thread dump operation to get extra lock info
String pid = args[optionCount];
...
runThreadDump(pid, params);
}
-Fが渡されるので、runJStackToolが呼び出されてSun.jvm.hotspot.tools.JStackをロードし、直接呼び出すのと同じ効果があります。
bin\Java -Dsun.jvm.hotspot.debugger.useWindbgDebugger -Dsun.jvm.hotspot.debugger.useProcDebugger -cp lib/sa-jdi.jar;lib/tools.jar Sun.jvm.hotspot.tools.JStack pid
sun.jvm.hotspot.tools.JStackは Sun.jvm.hotspot.bugspot.BugSpotAgent attach-> go-> setupVM methodを呼び出します
多分コードの下は魔法です
jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
if (jvmdi.canAttach()) {
jvmdi.attach();
jvmdi.setCommandTimeout(6000);
debugPrintln("Attached to Serviceability Agent's JVMDI module.");
// Jog VM to suspended point with JVMDI module
resume();
suspendJava();
suspend();
debugPrintln("Suspended all Java threads.");
}
これは、ターゲットプロセスのすべてのJava=スレッドを中断します。アプリケーションがスレッド枯渇のためにハングしている場合、suspendメソッドの呼び出しによってそれらが緩和される場合があります。