web-dev-qa-db-ja.com

(不明なソース)例外スタックトレース

バックグラウンド

この質問はに関連しています なぜString.valueOf(null)はNullPointerExceptionをスローしますか?

次のスニペットを検討してください。

_public class StringValueOfNull {
    public static void main(String[] args) {
        String.valueOf(null);

        // programmer intention is to invoke valueOf(Object), but instead
        // code invokes valueOf(char[]) and throws NullPointerException
    }
}
_

リンクされた質問への答えで説明したように、Javaのメソッドのオーバーロードは、上記の呼び出しを String.valueOf(char[]) に解決します。これにより、実行時にNullPointerExceptionが正しく生成されます。

Eclipseと_javac 1.6.0_17_でコンパイルされた、これはスタックトレースです。

_Exception in thread "main" Java.lang.NullPointerException
        at Java.lang.String.<init>(Unknown Source)
        at Java.lang.String.valueOf(Unknown Source)
        at StringValueOfNull.main(StringValueOfNull.Java:3)
_

上記のスタックトレースには、[〜#〜] key [〜#〜]情報がないことに注意してください。[~# 〜] not [〜#〜]valueOfメソッドの完全なシグネチャを持ちます! String.valueOf(Unknown Source)とだけ書かれています!

私が遭遇したほとんどの状況では、例外スタックトレースには常に、実際にスタックトレースにあるメソッドの完全なシグネチャがあります。もちろん、これはvery helpです。すぐに問題とスタックトレース(言うまでもなく構築するのにかなり費用がかかる)が提供される主な理由。

それでも、この場合、スタックトレースはまったく役に立ちません。プログラマーが問題を特定するのを助けることに悲惨なほど失敗しました。

現状では、プログラマーが上記のスニペットで問題を特定できる3つの方法を見ることができます。

  • プログラマは、メソッドがオーバーロードされていることを自分で認識し、解決規則により、この場合「間違った」オーバーロードが呼び出されます
  • プログラマーは適切なIDEを使用して、どのメソッドが選択されているかをすぐに確認できるようにします
    • たとえば、Eclipseでは、上記の式にマウスを合わせると、String valueOf(char[] data)が実際に選択されていることがプログラマーにすぐにわかります
  • プログラマーがバイトコードを調べます(ugh!)

最後のオプションはおそらく最もアクセスしにくいですが、もちろん究極の答えです(プログラマーはオーバーロードルールを誤解する可能性がありますIDEはバグがあるかもしれませんが、バイトコードは常に(?)行われます)。


質問

  • この場合、実際にスタックトレース内にあるメソッドのシグネチャに関して、なぜスタックトレースがそれほど有益ではないのですか?
    • これはコンパイラーによるものですか?ランタイム?他に何か?
  • スタックトレースがこれらのような重要な情報の取得に失敗する他の(まれな?)シナリオは何ですか?
49

これは通常、不足しているデバッグ情報に関連しています。おそらくrt.jarクラスのデバッグ情報が含まれていない(JDKではなく)JREを使用している可能性があります。完全なJDKを使用してみてください。スタックトレースで適切な場所を取得できます。

Exception in thread "main" Java.lang.NullPointerException
    at Java.lang.String.<init>(String.Java:177)
    at Java.lang.String.valueOf(String.Java:2840)
    at StringValueOfNull.main(StringValueOfNull.Java:3)
29
unbeli

Antビルドを使用していて、javacコマンドでdebug属性がfalseに設定されている場合、これが発生する可能性があることに注意してください。

例:トレースセットで適切な場所が必要な場合debug = true Antビルドで、

    <javac verbose="false" srcdir="${src}" destdir="${classdir}" debug="true" includes="**/*.Java">
        <classpath refid="compile.classpath" />
    </javac>
100
Supun Sameera

私は同じ問題を抱えていた、私はspringApache antを継続的な統合に使用している。

エラーはbuild.xmlファイルにありました。

より正確なコンテンツを含む性別変更ログは次のとおりです。

エラーが発生したbuild.xml:

    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes">
        <classpath refid="compile.classpath" />
    </javac>

エラーなしのbuild.xml:

    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes"  debug="true">
        <classpath refid="compile.classpath" />
    </javac>

構造内で私は勇気に欠けていましたdebug = "true"

6
jamlhet

Eclipseでコードを実行すると、次の出力が得られました。

public class Aloof {
    public static void main(String[] args) {
        String.valueOf(null);
    }
}

Exception in thread "main" Java.lang.NullPointerException
    at Java.lang.String.<init>(String.Java:177)
    at Java.lang.String.valueOf(String.Java:2840)
    at mysql.Aloof.main(Aloof.Java:19)

完全なソース(JDKから)を含めると、実際にString.Javaの177行目までデバッグできます。

3
bragboy

Eclipseの場合:Preferences> Java> Installed JREs。チェック済みのエントリには、JDK内のパスが必要です(例:C:\ Program Files(x86)\ Java\jdk1.7.0_55\jre)。

1
Peter Tseng

これは、ソースにデバッグ(行)情報がない場合、またはVMがクラスのロード時にその情報を破棄するように指示されている場合に発生します。行番号があるため、VM設定ではなく、クラスStringにデバッグ情報がありません。

1
Aaron Digulla