スレッド ダンプの生成

システム管理

このページの内容

お困りですか?

アトラシアン コミュニティをご利用ください。

コミュニティに質問

操作の実行中に、Jira がフリーズしたように見える場合があります。そのような場合、スレッド ダンプ — Java 仮想マシン内で実行中のスレッドおよびプロセスに関する情報を含むログ — の取得が役立つ可能性があります。スレッド ダンプの取得は非破壊プロセスであるため、稼動中のシステム上で実施することができます。このドキュメントでは、スレッド ダンプの取得に必要な手順を説明します。

Jira を実行している OS に応じて、スレッド ダンプを取得するのに必要なステップが異なります。次に示すステップから適切なものをご利用ください。

On this page:

Windows 環境

startup.bat で実行している Jira の場合

コマンド コンソールを管理者として実行する必要があります。


  1. Jira を実行しているコマンド コンソール ウィンドウで、タイトル バーを右クリックしてプロパティ ダイアログ ボックスを開き、[プロパティ] を選択します。
  2. [Layout] タブを選択します。
  3. [画面のバッファ サイズ] で [高さ] を 3000 に設定します。
  4. [OK] を選択します。
  5. 同じコマンド コンソールで CTRL-BREAK を押すと、コマンド コンソールにスレッド ダンプが出力されます。
  6. "Full thread dump" と書かれた行まで、コマンド コンソールをスクロールします。
  7. タイトル バーを右クリックして [編集] > [マーク] の順に選択します。スレッド ダンプのテキスト全体をハイライトします。
  8. タイトル バーを右クリックして [編集] > [コピー] の順に選択します。これでスレッド ダンプをテキスト ファイルに貼り付けられるようになりました。
     

Windows サービスとして実行している Jira の場合

jstack を使用する場合

JDK には‬ jstack という名前の、スレッド ダンプ生成用のツールが付属します。

  1. プロセスを特定します。‪Ctrl + Shift + Esc‬ キーを押してタスク マネージャーを立ち上げ、 Java (Jira) プロセスのプロセス ID を検索します。[View‪‬] > [Select Columns ...] を使用して PID 列を追加する必要がある場合があります。
  2. jstack を実行して、設定された間隔で単一または複数のスレッド ダンプをキャプチャします。

    単一のスレッド ダンプをキャプチャする...

    次のコマンドを使用して、プロセス ID <JIRA_PID> の単一のスレッド ダンプをキャプチャします。

    jstack.exe -l <JIRA_PID> > threaddump.txt

    たとえば、PID が 22668 の場合は次のように入力します。

    jstack.exe -l 22668 > threaddump.txt

    これによって、現在のディレクトリの threaddump.txt に出力されます。

    設定された間隔で複数のスレッド ダンプをキャプチャ...

    次のコマンドを使用して、各スレッド ダンプ間において、プロセス ID <JIRA_PID> のスレッド ダンプ 6 個を 10 秒間隔でキャプチャします。

    for /L %n in (1,1,6) do timeout 10 | jstack.exe -l <JIRA_PID> > threaddump-%n.txt

    たとえば、PID が 22668 の場合は次のように入力します。

    for /L %n in (1,1,6) do timeout 10 | jstack.exe -l 22668 > threaddump-%n.txt

    これは threaddump-%n.txt に出力されます。ここで %n は、ループの反復回数 (1 から始まる) です。

    timeout コマンド パラメーターを変更し、各スレッド ダンプ間の時間を調整し、in (start,step,end) 句の範囲を変更し、キャプチャするスレッド ダンプの数を調整できます。(1,1,6) 上記の例の範囲は、次のことを意味します。

    • 先頭が 1
    • 増分単位: 1
    • 末尾が 6

    ‪ jstack‬ のよくある問題

    • jstack は Jira を実行しているユーザーと同じユーザーで実行する必要があります。
    • エラー "Not enough storage is available to process this command (このコマンドを実行するのに十分な記憶域がありません)" が表示された場合は、ここから‪ "psexec" ユーティリティをダウンロードして次のコマンドを実行します。ここで <JIRA_PID> は、Jira プロセス ID (22668 など) です。

      • 単一スレッド ダンプをキャプチャする場合

        jstack.exe -l <JIRA_PID> > threaddump.txt
      • 設定した間隔で複数のスレッド ダンプをキャプチャする場合

        1..6|foreach{jstack -l <JIRA_PID> |Out-File -FilePath "app_threads.$(Get-Date -uformat %s).txt";sleep 10}
    • 実行可能な jstack が $PATH にない場合は、<JDK_HOME>/bin ディレクトリで探します。
    • java.lang.NoClassDefFoundError: sun/tools/jstack/JStack が発生したら、JDK の lib ディレクトリ tools.jar があるかどうかを確認します。tools.jar がない場合、JDK のフル バージョンをダウンロードします。

Linux / Unix / OS X 環境

Linux/Unix コマンドライン

  1. Jira を実行している java プロセスを識別します。これは次のようなコマンドで実現できます。

    ps -ef | grep java

    次のようなプロセスが見つかります。

    keithb     910   873  1 17:01 pts/3    00:00:18 /usr/java/jdk/bin/java -Xms128m -Xmx256m
    -Xms128m -Xmx256m -Djava.awt.headless=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
    -Djava.awt.headless=true -Djava.endorsed.dirs=/tmp/atlassian-jira-enterprise-3.6-standalone/common/endorsed
    -classpath :
  2. スレッド ダンプを取得するには、次のコマンドを実行します。

    単一キャプチャの場合

    kill -3 <pid>

    複数キャプチャの場合

    for i in $(seq 6); do top -b -H -p <pid> -n 1 > jira_cpu_usage.`date +%s`.txt; kill -3 <pid>; sleep 10; done

    pid はプロセス ID (この場合は 910) です。

  3. スレッド ダンプは、Tomcat のコンソール出力に記載されます。コンソール出力は logs/catalina.out ファイル (Jira スタンドアロン / インストーラーの場合は Jira アプリケーション インストール ディレクトリにあります) にリダイレクトされます。

Linux/Unix での代替手段: jstack を使用してスレッドダンプを生成する

スレッド ダンプを取得する際 kill -3 <pid> で問題が発生した場合、java ユーティリティ である jstack を使用し、指定したプロセスの Java スレッドのスタックトレースを出力します。

  1. Jira を実行している java プロセスを特定します。これは次のようなコマンドで実現できます。

    ps -ef | grep java

    次のようなプロセスが見つかります。

    adam 22668 0.3 14.9 1691788 903928 ? Sl Jan27 9:36 /usr/lib/jvm/java-6-sun-1.6.0.14/bin/java -Djava.util.logging.config.file=/home/adam/Products/installs/atlassian-jira-enterprise-4.0.1-standalone/conf/logging.properties -XX:MaxPermSize=256m -Xms128m -Xmx1048m -Djava.awt.headless=true -Datlassian.standalone=JIRA -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true -Dmail.mime.decodeparameters=true -Datlassian.mail.senddisabled=false -Datlassian.mail.fetchdisabled=false -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/home/adam/Products/installs/atlassian-jira-enterprise-4.0.1-standalone/common/endorsed -classpath /home/adam/Products/installs/atlassian-jira-enterprise-4.0.1-standalone/bin/bootstrap.jar -Dcatalina.base=/home/adam/Products/installs/atlassian-jira-enterprise-4.0.1-standalone -Dcatalina.home=/home/adam/Products/installs/atlassian-jira-enterprise-4.0.1-standalone -Djava.io.tmpdir=/home/adam/Products/installs/atlassian-jira-enterprise-4.0.1-standalone/temp org.apache.catalina.startup.Bootstrap start
  2. jstack を実行して、設定された間隔で単一または複数のスレッド ダンプをキャプチャします。

    単一のスレッド ダンプをキャプチャする...

    次のコマンドを使用して、プロセス ID <JIRA_PID> の単一のスレッド ダンプをキャプチャします。

    jstack <JIRA_PID> > threaddump.txt

    たとえば、PID が 22668 の場合は次のように入力します。

    jstack 22668 > threaddump.txt

    出力は現在のディレクトリの threaddump.txt に保存されます。

    設定された間隔で複数のスレッド ダンプをキャプチャ...

    次のコマンドを使用して、各スレッド ダンプ間においてプロセス ID <JIRA_PID> のスレッド ダンプ 6 個を 10 秒間隔でキャプチャします。

    for i in $(seq 6); do top -b -H -p <JIRA_PID> -n 1 > threaddump.$(date +%s).txt; kill -3 <JIRA_PID>; sleep 10; done

    たとえば、PID が 22668 の場合は次のように入力します。

    for i in $(seq 6); do top -b -H -p 22668 -n 1 > threaddump.$(date +%s).txt; kill -3 22668; sleep 10; done

    出力は現在のディレクトリの threaddump.$(date +%s).txt に保存されます。date +%s は現在の Unix タイムスタンプです。

    seq コマンド パラメーターを変更してキャプチャするスレッド ダンプの数を調整し、sleep コマンド パラメーターを変更して次のスレッド ダンプまでの時間を調整できます。

    RDP 経由でサーバーに接続している場合、jstack は次のエラーで失敗する可能性があります。

    Not enough storage is available to process this command 

    コンソールモードで RDP セッションを開く必要があります: mstsc /admin

Linux/Unix での代替手段: スクリプトを使用してスレッドダンプを生成する

また、サポート チームが作成したスクリプトを使用してスレッド ダンプを生成することもできます。これは簡単なプロセスで、スクリプトがすべての操作を実行します。スクリプトはスレッド ダンプを生成するだけでなく、ヒープ ダンプを生成、ディスクのアクセス速度や Java SSL 接続をチェックすることもできます。

  1. (オプション) お使いの Jira バージョンでサポートされている場合、Thready アプリをインストールします。Thready はスレッドを分析しやすくするよう、 Tomcat スレッドの名前を変更して名前に URL を含めます。
  2. https://bitbucket.org/atlassianlabs/atlassian-support/ からスクリプトをダウンロードしてインストールします。
  3. Jira インスタンスの動作が遅い、または反応がない場合はスクリプトを実行します。 
    1. (オプション) また、スクリプトにより、ディスクのアクセス速度をテストすることもできます。詳細は、「ディスクのアクセス速度のテスト」に記載されています。 
    2. スレッド ダンプを取得するかどうかを尋ねられたら、「Y」を入力します。
    3. ヘッド ダンプを取得するかどうかを尋ねられたら、「Y」を入力します。
    4. (オプション) また、スクリプトで Java SSL 接続をチェックすることもできます。
  4. スクリプトを実行した後、スレッド ダンプが取得され、圧縮されます。これで、サポート チケットを開き、生成されたパッケージを添付できます。

Atlassian Docker コンテナーのステップ

Jira をコンテナーで実行している場合は、次の手順に従います。

/opt/atlassian/support/thread-dumps.shdocker exec を介して実行すると、スレッド ダンプの収集をコンテナー化されたアプリから簡単にトリガーできます。次に例を示します。

docker exec my_container /opt/atlassian/support/thread-dumps.sh

初期設定では、このスクリプトはスレッド ダンプ 10 個を 5 秒間隔で収集します。-c / --count-i / --interval をそれぞれ使用することで、これはカウントと間隔のカスタム値を渡して上書きできます。たとえば、スレッド ダンプ 20 個を 3 秒間隔で収集するには、次のようにします。

docker exec my_container /opt/atlassian/support/thread-dumps.sh --count 20 --interval 3

Docker コンテナーを Kubernetes 環境で実行している場合は、次のようにコマンドを実行できます。

kubectl exec -it jira-1 -n jira -- bash -c "/opt/atlassian/support/thread-dumps.sh --count 20 --interval 3"

-it jira-1 をポッド名に置き換えて、-n jira を Jira ポッドが実行されている名前スペースに置き換えます。

スレッド ダンプは $APP_HOME/thread_dumps/<date> に書き込まれます。

注: 初期設定では、このスクリプトは「スレッドモード」のトップ ランからの出力もキャプチャします。これは、-n / --no-top を渡すことで無効にできます。

追加情報は https://hub.docker.com/r/atlassian/jira-software の「トラブルシューティング」セクションをご参照ください。 

分析ツール

スレッド ダンプを調査するには、WatsonTDA、または Samurai をお試しください。

TDA

  1. TDA をダウンロードします。
  2. CD コマンドを JAR が存在するディレクトリに格納します。
  3. 次のコマンドを実行します。

    java -jar -Xmx512M ~/tda-bin-1.6/tda.jar
  4. スレッドダンプが含まれている catalina.out ファイルを開きます。

TDA でスレッド ダンプを処理する場合の問題 (NumberFormatException)

TDA コンソールに次のようなエラーが表示されます。

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "5 os_prio=0"
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.lang.Long.parseLong(Long.java:441)
        at java.lang.Long.<init>(Long.java:702)
        at com.pironet.tda.utils.ThreadsTableModel.getValueAt(ThreadsTableModel.java:80)
        at com.pironet.tda.utils.TableSorter.getValueAt(TableSorter.java:285)
        at javax.swing.JTable.getValueAt(JTable.java:2717)
        at javax.swing.JTable.prepareRenderer(JTable.java:5719)
        at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2114)
        at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2016)
        at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1812)
        at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
        at javax.swing.JComponent.paintComponent(JComponent.java:778)
        at javax.swing.JComponent.paint(JComponent.java:1054)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JViewport.paint(JViewport.java:731)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1047)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JComponent.paintToOffscreen(JComponent.java:5230)
        at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:295)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1249)
        at javax.swing.JComponent._paintImmediately(JComponent.java:5178)
        at javax.swing.JComponent.paintImmediately(JComponent.java:4989)
        at javax.swing.RepaintManager$3.run(RepaintManager.java:808)
        at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
        at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
        at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
        at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1677)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
        at java.awt.EventQueue.access$200(EventQueue.java:103)
        at java.awt.EventQueue$3.run(EventQueue.java:694)
        at java.awt.EventQueue$3.run(EventQueue.java:692)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

スレッド ダンプで次のコマンドを適用し、スレッド ヘッダー形式を修正して処理できるようにします:
sed -i 's/prio=[0-9]\{1,2\} os_prio=[0-9]\{1,2\}/prio=5/g' <filename>

Mac の場合:

sed -i '' 's/prio=[0-9]\{1,2\} os_prio=[0-9]\{1,2\}/prio=5/g' <filename>

スレッドダンプについて知りたい場合は、ナレッジベース記事をご参照ください:

最終更新日 2022 年 7 月 14 日

この内容はお役に立ちましたか?

はい
いいえ
この記事についてのフィードバックを送信する
Powered by Confluence and Scroll Viewport.