スレッド ダンプの生成
ご利用のアトラシアン アプリケーションが応答を返さなくなったり、アトラシアン アプリケーションのパフォーマンスが低下したりした場合に、アトラシアン サポートで問題の診断のためにスレッド ダンプの提供を依頼させていただくことがあります。スレッド ダンプは、Java 仮想マシン内で現在実行されているスレッドとプロセスの情報を含むログです。スレッド ダンプの取得は非破壊プロセスであるため、実行中のシステム上で実施することができます。このドキュメントでは、スレッド ダンプの取得に必要な手順を説明します。
スレッド ダンプの取得に必要な手順は、サーバーのオペレーティング システム (Windows または Linux) に応じて異なります。また、スレッド ダンプを手動で取得することも、サポート スクリプトを使用してスレッド ダンプを自動的に取得することもできます。お客様の支援のためにサポートで必要となる情報を取得できるように設計されている、サポート スクリプトの使用をおすすめします。
スレッドを時間別に比較できるよう、一連のスレッド ダンプを生成することをおすすめします。アトラシアン サポートでは一般に、1 分間で 10 秒間隔のスレッド ダンプを 6 つ取得することを推奨しています。
スレッド ダンプの自動生成
Windows and Linux environment using Java Flight Recorder (JFR)
JFR is bundled in the following Atlassian applications (via Troubleshooting and Support Tools app), and continuous diagnostic data recording begins as soon as you start up your instance:
Jira Data Center and Server 9.0 and newer
Bitbucket Data Center and Server 8.3 and newer
Confluence Data Center and Server 7.20 and newer
Thread dumps are a part of the diagnostic data that is automatically captured by JFR. Within our applications, we've changed the default frequency for gathering thread dumps to once every 10 seconds.
This set of thread dumps would then be automatically saved to a binary .jfr file (in <Application-Home-Directory>/log/jfr
folder) every five minutes, together with the other diagnostics data (runtime events). Collected thread dumps within the binary .jfr file would need to be parsed using JDK Mission Control.
In addition to that, when a Support zip is being created, a new binary .jfr file would be created in the <Application-Home-Directory>/log/jfr
folder as well.
This latest .jfr binary file and thread dumps that are extracted from it will be included in the Support zip file (under jfr-bundle
folder). This set of extracted thread dumps are already in human-readable format and can be parsed by common thread analysis tools.
For more information on this, please refer to our Diagnosing runtime issues using the Java Flight Recorder documentation.
スレッド ダンプの手動生成
Windows 環境
次の手順にしたがってスレッド ダンプを手動で取得します。
The application running in the console window
- In the Command Console window where the application is running, open the properties dialog box by right-clicking on the title bar and selecting "Properties".
- [Layout] タブを選択します。
- [Screen Buffer Size] で、[Height] を 3000 に設定します。
- [OK] をクリックします。
- 同じコマンド コンソールで CTRL-BREAK を押すと、コマンド コンソールにスレッド ダンプが出力されます。
- "Full thread dump" と書かれた行まで、コマンド コンソールをスクロールします。
- Right-click the title bar and select Edit -> Mark. Highlight the entire text of the thread dump.
- Right-click the title bar and select Edit -> Copy. The thread dump can then be pasted into a text file.
The application runs as a Windows Service
jstack を使用する場合
JDK には jstack という名前の、スレッド ダンプ生成用のツールが付属します。
If you're using the JVM bundled with the product, please download and install a supported JDK, such as AdoptOpenJDK. Please make sure that the JDK is of the same major version as the JVM running the application, typically Java 8 or 11. If in doubt, run
java -version
to check
- Launch Windows Powershell as administrator
Run this command to set the PID to a variable
$APP_PID = (Get-Process -name "tomcat8.exe.x64").id
Alternatively, launch the task manager by, pressing
Ctrl + Shift + Esc
and find the Process ID of the Java process. You may need to add the PID column usingView
->Select Columns ...
If there are multiple Tomcat/application instances running, please get the PID manually for the right process.Run this
1..6|foreach{jstack -l $APP_PID|Out-File -FilePath "app_threads.$(Get-Date -uformat %s).txt";sleep 10}
This will create the
app_threads
files in the current directory.
jstack のよくある問題
- You must run jstack as an admin or as the same user that is running the application.
- エラー メッセージ "Not enough storage is available to process this command" が表示された場合、ここから "psexec" ユーティリティをダウンロードして、以下のコマンドを実行します。
psexec -s jstack <pid> >> threaddumps.txt
- If you are connecting to the server through RDP and getting "Not enough storage is available to process this command", you will need to open an RDP session in console mode:
mstsc /admin
- If the
jstack
executable is not in your$PATH
, then please look for it in your<JDK_HOME>/bin
directory java.lang.NoClassDefFoundError: sun/tools/jstack/JStack
が発生したら、JDK の lib ディレクトリに tools.jar があるかどうかを確認します。存在しない場合、JDK の完全なバージョンをダウンロードします (プロセスが実行されている JRE と同じバージョンの JDK をダウンロードするようにします)。
Linux / Unix / OS X 環境
Using jstack
これはスレッドとそれらの CPU 使用率の両方を提供するため、推奨される手法です。jstack は指定されたプロセスの Java スレッドのスタック トレースを出力する、java ユーティリティです。jstack に同梱される JDK がサーバーに必要です。
アプリケーションが実行されている Java プロセスを特定し、それを
APP_PID
環境変数に格納します。次のコマンドを実行します。
# seq 6, will run the command 6 times # sleep 10, will wait for 10 seconds for i in $(seq 6); do top -b -H -p $APP_PID -n 1 > app_cpu_usage.`date +%s`.txt; jstack $APP_PID > app_threads.`date +%s`.txt; sleep 10; done
アプリケーションをサービスとして実行している場合、次のコマンドを実行して、アプリケーション サービスを実行しているユーザーを確認します。
# seq 6, will run the command 6 times # sleep 10, will wait for 10 seconds for i in $(seq 6); do top -b -H -p $APP_PID -n 1 > app_cpu_usage.`date +%s`.txt; sudo -u $APP_USER jstack $APP_PID > app_threads.`date +%s`.txt; sleep 10; done
現在のディレクトリに、
app_cpu_usage.<DATE>.txt
およびapp_threads.<DATE>.txt
が結果として出力されます。
生成されたスレッド ダンプの分析
Look in the CPU usage files to identify which threads are consistently using a lot of CPU time
CPU 時間を使用している上位 10 個のスレッドの PID を記録し、それらを 16 進数に変換します。例: 11159 -> 0x2b97
16 進数の値をスレッド ダンプで検索し、CPU を使用しているスレッドを特定します。
kill シグナルの使用
If the JDK and jstack are not available on the server, a kill signal can be sent to the Java process to produce a thread dump.
アプリケーションが実行されている 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 :
スレッド ダンプを取得するには、次のコマンドを実行します。
# seq 6, will run the command 6 times # sleep 10, will wait for 10 seconds for i in $(seq 6); do top -b -H -p $APP_PID -n 1 > app_cpu_usage.`date +%s`.txt; kill -3 $APP_PID ; sleep 10; done
where $APP_PID is the process id — in this case, 910.
スレッド ダンプが Tomcat のコンソール出力に記載されます。コンソール出力は
logs/catalina.out
ファイル (アプリケーション インストール ディレクトリにあります) にリダイレクトされます。
スレッド ダンプの分析のための一般的な分析ツール
Try TDA, IBM TMDA (JCA) or Samurai to inspect your thread dump.
TDA
- TDA をダウンロードします。
- JAR が存在するディレクトリに
CD
します。 次のコマンドを実行します。
java -jar -Xmx512M ~/tda-bin-1.6/tda.jar
- スレッド ダンプを含む
catalina.out
ファイルを開きます。
TDA でスレッド ダンプを処理する場合の問題 (NumberFormatException)
Should you get an error on the TDA console like:
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)
これを処理可能にするには、スレッド ダンプに次のコマンドを適用して、スレッドのヘッダーの形式を修正します。
Linux
sed -i 's/prio=[0-9]\{1,2\} os_prio=-\?[0-9]\{1,2\}/prio=5/g' <filename>
Mac
sed -i '' -E 's/prio=[0-9]{1,2} os_prio=-?[0-9]{1,2}/prio=5/g' <filename>