ページの先頭行へ戻る
Interstage Application Server V13.0.0 チューニングガイド
FUJITSU Software

7.6.1 スタックトレース

Javaアプリケーションで例外(java.lang.Throwableのインスタンス)がスローされた場合などに出力されるスタックトレースは、エラーが発生するまでの経緯(メソッドの呼び出し順番)が示されています。このスタックトレースを解析することにより、エラーが発生した箇所と原因を確認することができます。

スタックトレースの出力先

スタックトレースの出力先は、標準エラーです。通常のJavaアプリケーションの場合は、コンソールに出力されますが、Jakarta Servlet/Jakarta Server Pages/EJBアプリケーションの場合は、ログファイル(標準出力、標準エラー出力あるいはJava VMの出力を格納するファイルなど)に出力されます。

スタックトレースの出力方法

Javaでスローされた例外をcatch節でキャッチし、例外のprintStackTraceメソッドを実行することにより、スタックトレースを出力することができます。

java.lang.Throwable.printStackTrace()メソッドでスタックトレースを出力する方法

try {
    SampleBMPSessionRemote bmpSessionRemote = bmpSessionHome.create();
} catch(Exception e) {
    e.printStackTrace();
}

なお、スローされた例外をtry-catch構文で処理するメソッドがスレッドにない場合、そのスレッドは停止され、Java VMによってスタックトレースが出力されます。

スタックトレースの出力フォーマット

例外クラス名: エラーメッセージ
  at クラス名.メソッド名1(ソース名:行番号)    呼び出し先
  at クラス名.メソッド名2(ソース名:行番号)
             :
             :
  at クラス名.メソッド名N(ソース名:行番号)    呼び出し元

7.6.1.1 スタックトレースの解析方法(その1)

以下の出力例をもとにして、解析方法を説明します。
先頭の“数字:”は、説明の便宜上、付加しています。

1:java.lang.NullPointerException
2:  at agency.attestation.CheckLoginInfo.doCheck(CheckLoginInfo.java:150)
3:  at agency.attestation.AttestationServlet.doGet(AttestationServlet.java:96)
4:  at agency.attestation.AttestationServlet.doPost(AttestationServlet.java:161)
5:  at javax.servlet.http.HttpServlet.service(HttpServlet.java:772)
6:  at javax.servlet.http.HttpServlet.service(HttpServlet.java:865)
              :

読み方

スタックトレースは、6行目から上方向に読むと、次の流れで例外が発生したことがわかります。

  1. javax.servlet.http.HttpServlet.service()が、HttpServlet.javaの865行目で、javax.servlet.http.HttpServlet.service()を実行し、

  2. javax.servlet.http.HttpServlet.service()が、HttpServlet.javaの772行目で、agency.attestation.AttestationServlet.doPost()を実行し、

  3. agency.attestation.AttestationServlet.doPost()が、AttestationServlet.javaの161行目で、agency.attestation.AttestationServlet.doGet()を実行し、

  4. agency.attestation.AttestationServlet.doGet()が、AttestationServlet.javaの96行目で、agency.attestation.CheckLoginInfo.doCheck()を実行した結果、

  5. agency.attestation.CheckLoginInfo.doCheck()内のCheckLoginInfo.javaの150行目で、java.lang.NullPointerExceptionという例外が発生した

解析方法

スタックトレースの解析例を、次に示します。

  1. 1行目の例外情報から、原因を特定できるかどうか確認します。
    NullPointerExceptionがスローされていることがわかります。

  2. 2行目のCheckLoginInfo.javaの開発担当者であれば、150行目の実装に問題がないかどうかを確認します。

  3. 2行目のCheckLoginInfo.javaの開発担当者でない場合、スタックトレース中で最上行にある開発担当者が開発したクラスを探します。そして、そのクラスの実装に問題がないかどうかを確認します。それでも、原因を特定できない場合は、開発したクラスが使用しているクラスの提供元に調査を依頼します。

または、スタックトレースが、想定された流れでメソッドを実行しているかどうかを確認するのも1つの方法です。

7.6.1.2 スタックトレースの解析方法(その2)

以下の出力例をもとにして、解析方法を説明します。
先頭の“数字:”は、説明の便宜上、付加しています。

1:java.util.MissingResourceException: Can't find bundle for base name sample.SampleResource, locale ja_JP
2:  at java.util.ResourceBundle.throwMissingResourceException(Unknown Source)
3:  at java.util.ResourceBundle.getBundleImpl(Unknown Source)
4:  at java.util.ResourceBundle.getBundle(Unknown Source)
5:  at sample.SampleMessage.getMessage(SampleMessage.java:15)
6:  at sample.SampleServlet.doGet(SampleServlet.java:10)
7:  at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
8:  at javax.servlet.http.HttpServlet.service(HttpServlet.java:809)
    :
    :

解析方法

スタックトレースの解析例を、次に示します。

  1. 1行目の例外情報から、原因を特定できないかを確認します。

    APIリファレンスによると、java.util.MissingResourceExceptionは、Javaのリソースがない場合に発生する例外です。また、エラーメッセージによると、sample.SampleResourceというリソースファイルの日本語版(ja_JP)がないということがわかります。

  2. リソースファイルを確認します。

    1. リソースファイル名を誤っていないか

      SampleMessage.javaの15行目のsample.SampleMessage.getMessage ()内で、java.util.ResourceBundle.getBundle()を実行した結果、例外がスローされています。したがって、そこでjava.util.ResourceBundle.getBundle()に渡しているリソースファイル名に誤りがないかどうかを確認します。

    2. リソースファイルが、所定のディレクトリ構成内に存在するか

      a)のリソースファイル名が正しい場合、所定のディレクトリ構成(/sample/)に、次のどれかのリソースファイルがあるかどうかを確認します。

      • SampleResource_ja_JP.properties

      • SampleResource_ja_JP.class

      • SampleResource_ja.properties

      • SampleResource_ja.class

      • SampleResource.properties

      • SampleResource.class

7.6.1.3 スタックトレースの解析方法(その3)

以下により、原因となる例外のスタックトレースが出力されます。

以下のサンプルを使って、説明します。

1 :public class Test {
2 :
3 :    public static void main(String[] args) {
4 :       new Test();
5 :    }
6 :
7 :    Test() {
8 :        try{
9 :            parentMethod();
10:        } catch (Exception e) {
11:            e.printStackTrace();
12:        }
13:    }
14:
15:    void parentMethod() throws HiLevelException {
16:        try {
17:            childMethod();
18:        } catch (Exception e) {
19:            throw new HiLevelException("HiLevel", e);
20:        }
21:    }
22:
23:    void childMethod() throws LowLevelException {
24:        throw new LowLevelException("LowLevel");
25:    }
26:}
27:
28:class HiLevelException extends Exception {
29:    HiLevelException(String msg, Throwable cause) {
30:        super(msg, cause);
31:    }
32:}
33:
34:class LowLevelException extends Exception {
35:    LowLevelException(String msg) {
36:        super(msg);
37:    }
38:}

サンプルを実行すると、以下のスタックトレースが出力されます。

HiLevelException: HiLevel
    at Test.parentMethod(Test.java:19)
    at Test.<init>(Test.java:9)
    at Test.main(Test.java:4)
Caused by: LowLevelException: LowLevel
    at Test.childMethod(Test.java:24)
    at Test.parentMethod(Test.java:17)
    ... 2 more

HiLevelExceptionに続いて、“Caused by:”以降に、原因となるLowLevelExceptionのスタックトレースが出力されています。最終行の“... 2 more”は、“Caused by:”の直前の2行が続きのスタックトレースであることを示しています。
つまり、以下のように解釈することができます。

原因となる例外の解釈

Caused by: LowLevelException: LowLevel
    at Test.childMethod(Test.java:24)
    at Test.parentMethod(Test.java:17)
    at Test.<init>(Test.java:9)
    at Test.main(Test.java:4)

以上から、次のことがわかります。

詳細は、Java APIリファレンスのjava.lang.ThrowableのprintStackTraceメソッドの解説を参照してください。