web-dev-qa-db-ja.com

jstack -Fは実行中のJavaプロセスにどのように影響しますか?

Java使用しているWebアプリケーション(Jenkins)が応答しなくなる問題を診断しようとしています。jstack-Fフラグなしで実行すると、何もしませんが、フラグを設定してスレッドダンプを強制すると、結果が得られるだけでなく、アプリケーションが応答を開始し、最終的に再び応答を停止するまで何も起こらなかったかのように続行します。

jstack -Fフラグは、実行中のJVMに影響を与え、応答しないアプリケーションが再び応答を開始する原因になりますか?

28
Jordan Bentley

Jstackのソースを見ることができます here 。 -F引数は、jstackがjvmに接続する方法を変更します。 -F(または-m)を使用すると、JStackはJavaデバッガーインターフェースを使用してjvmに接続します。pidが指定されている場合、JStackは SA PID Attaching Connector と接続しますと言う、

デバッグするプロセスは、デバッグモードで(つまり、-agentlib:jdwpまたは-Xrunjdwpを使用して)開始されている必要はありません。プロセスがhungであっても問題ありません。

なぜ応答しないアプリケーションが再び応答を開始するのかはわかりませんが、上のリンクには、

プロセスは、このコネクタが接続されると中断され、このコネクタが切断されると再開されます。

これが影響する可能性があります。

15
sbridges

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メソッドの呼び出しによってそれらが緩和される場合があります。

11
Ted Shaw