スレッドダンプの解析では、障害の推定原因に応じて解析方法が異なる。それぞれの推定原因に応じた解析方法について説明しよう。
バックプロセス無応答の疑いがある場合には、スレッドダンプを複数回取得しておき、時系列で観察して同一スレッドIDでの比較調査を行う。調査のポイントは、次の3つだ。
【調査のポイント】
これらの特徴を持つスレッドを見つけ出し、どこでハングアップしているかを調べる。下記にスレッドダンプの例を示そう。
"Thread-1" prio=9 tid=0x54c3a70 nid=723 runnable [0x4ff27000..0x4ff27438] at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvLib.send (Native Method) at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvLib.sendData(JdbcDbpsvLib.java:311) at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvResultSQLExecute.SQLGetResult(JdbcDbpsvResultSQLExecute.java:1488) 【略】
"Thread-1" prio=9 tid=0x54c3a70 nid=723 runnable [0x4ff27000..0x4ff27438] at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvLib.send (Native Method) at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvLib.sendData(JdbcDbpsvLib.java:311) at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvResultSQLExecute.SQLGetResult(JdbcDbpsvResultSQLExecute.java:1488) 【略】
"Thread-1" prio=9 tid=0x54c3a70 nid=723 runnable [0x4ff27000..0x4ff27438] at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvLib.send (Native Method) at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvLib.sendData(JdbcDbpsvLib.java:311) at JP.co.Hitachi.soft.DBPSV_Driver.JdbcDbpsvResultSQLExecute.SQLGetResult(JdbcDbpsvResultSQLExecute.java:1488) 【略】
【解析のポイント】
スレッドダンプを複数回取得して、時系列で観察し、同じスレッドIDのスタックトレースを比較調査する。
上記の例では、Native Method実行の応答が返ってこないためハングアップが発生している。この場合、「tid=0x54c3a70」のスレッドが複数のスレッドダンプで同じ場所を実行中となっていて、このスレッドがデータベースからの応答を待っているため、ハングアップが発生していると分かる。
デッドロックの疑いがある場合には、スレッドが取得しているロックオブジェクトの関係に着目して解析する。デッドロックを調査する場合のポイントは、次の3つだ。
【調査のポイント】
デッドロックの場合のスレッドダンプの例を以下に示そう。
"Thread-5" prio=5 tid=0x0096A4B8 nid=0x40c runnable [af8f000..af8fdb4] at deadlock.run(deadlock.java:48) "Thread-3" prio=5 tid=0x008FEFB0 nid=0x5b0 waiting for monitor entry [af0f000..af0fdb4] at deadlock.run(deadlock.java:42) - waiting to lock <02A328C0> (a java.lang.Object) - locked <02A328C8> (a java.lang.Object) "Thread-1" prio=5 tid=0x00900220 nid=0x234 waiting for monitor entry [ae8f000..ae8fdb4] at deadlock.run(deadlock.java:33) - waiting to lock <02A328C8> (a java.lang.Object) - locked <02A328C0> (a java.lang.Object)
【解析のポイント】
ポイント2、3に当てはまるスレッドに対し、ロックしているオブジェクトのアドレスをつき合わせながらデッドロックを検出する。上記の場合、Thread-3は、<02A328C8>のロックを取得して、かつ<02A328C0>の取得待ちを示している。一方、Thread-1は、<02A328C0>のロックを取得していて、かつ<02A328C8>の取得待ちとなっていて、Thread-3とThread-1がデッドロックしていることが分かる。
なお、「バックプロセス無応答の原因がJavaと外部リソースの間でのロックの掛け合いである」というケースもある。この場合は、外部リソース側のロックはスレッドダンプには現れないので注意が必要だ。
無限ループの疑いがある場合も、スレッドダンプを複数回取得しておき、時系列で同一スレッドIDに対して比較調査を行う。調査のポイントは、次の3つだ。
【調査のポイント】
以下に、無限ループの場合のスレッドダンプファイルの例を示すので、これらの特徴を持つスレッドを見つけ出し、どこで無限ループに陥っているかを調べてみよう。
"Ajp13Processor[8007][80]" daemon prio=1 tid=0x312d5ee8 nid=0x1b24 runnable [317ab000..317ad560] at java.security.AccessController.doPrivileged(Native Method) at org.apache.catalina.connector.HttpRequestBase.getSession(HttpRequestBase.java:1186) at org.apache.catalina.connector.HttpRequestFacade.getSession(HttpRequestFacade.java:209) at org.apache.catalina.connector.HttpRequestFacade.getSession(HttpRequestFacade.java:218) at org.apache.jsp.Jsp1$jsp._jspService(Jsp1$jsp.java:62) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:108) 【略】
"Ajp13Processor[8007][80]" daemon prio=1 tid=0x312d5ee8 nid=0x1b24 runnable [317ab000..317ad560] at org.apache.catalina.session.StandardSession.setAttribute(StandardSession.java:1207) at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:191) at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:191) at org.apache.jsp.Jsp1$jsp._jspService(Jsp1$jsp.java:62) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:108) 【略】
"Ajp13Processor[8007][80]" daemon prio=1 tid=0x312d5ee8 nid=0x1b24 runnable [317ab000..317ad560] at org.apache.catalina.session.StandardSession.setAttribute(StandardSession.java:1207) at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:191) at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:191) at org.apache.jsp.Jsp1$jsp._jspService(Jsp1$jsp.java:62) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:108) 【略】
【解析のポイント】
スレッドダンプを複数回取得して、時系列で観察し、同じスレッドIDのスタックトレースを比較調査する。
この場合、「tid=0x312d5ee8」のスレッドは、複数のスレッドダンプでJsp1$jsp.java:62の処理を実行しています。無限ループに陥っている可能性がある。
今回は、Java EEサーバでプロセスハングアップが発生した場合の問題解決の手順と、ログ・トレース、スレッドダンプの解析のポイントについて説明した。推定原因を定め、その情報を元に詳細原因を探ることで早期の原因特定が可能になるということだ。
Copyright © ITmedia, Inc. All Rights Reserved.