web-dev-qa-db-fra.com

(Source inconnue) dans la trace de la pile d'exceptions

Contexte

Cette question est liée à Pourquoi String.valueOf (null) lève-t-il une NullPointerException?

Considérez l'extrait de code suivant:

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
    }
}

Comme expliqué dans la réponse à la question liée, la surcharge de méthode de Java résout l'invocation ci-dessus en String.valueOf(char[]) , ce qui entraîne à juste titre un NullPointerException au moment de l'exécution.

Compilé dans Eclipse et javac 1.6.0_17, Voici la trace de la pile:

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)

Notez que la trace de pile ci-dessus ne contient pas les informations [~ # ~] [~ # ~] de la pile: elle le fait [~ # ~] pas [~ # ~] ont la signature complète de la méthode valueOf! Il dit simplement String.valueOf(Unknown Source)!

Dans la plupart des situations que j'ai rencontrées, les traces de pile d'exceptions ont toujours la signature complète des méthodes qui se trouvent réellement dans la trace de pile, ce qui bien sûr est très utile pour identifier le problème immédiatement et une raison majeure pour laquelle la trace de la pile (qui est inutile de dire qu'il est plutôt coûteux à construire) est fournie en premier lieu.

Et pourtant, dans ce cas, la trace de la pile n'aide pas du tout . Il a misérablement échoué en aidant le programmeur à identifier le problème.

En l'état, je peux voir 3 façons dont un programmeur peut identifier le problème avec l'extrait ci-dessus:

  • Le programmeur se rend compte par lui-même que la méthode est surchargée et, par règle de résolution, la surcharge "incorrecte" est invoquée dans ce cas
  • Le programmeur utilise un bon IDE qui lui permet de voir rapidement quelle méthode est sélectionnée
    • Dans Eclipse, par exemple, le survol de la souris sur l'expression ci-dessus indique rapidement au programmeur que la String valueOf(char[] data) est bien celle sélectionnée
  • Le programmeur examine le bytecode (ugh!)

La dernière option est probablement la moins accessible, mais bien sûr, c'est la réponse ultime (un programmeur peut mal comprendre la règle de surcharge, IDE peut être bogué, mais les bytecodes disent toujours (?) La vérité sur ce qui est en cours).


Questions

  • Pourquoi la trace de pile est-elle si peu informative dans ce cas en ce qui concerne les signatures des méthodes qui se trouvent réellement dans la trace de pile?
    • Est-ce dû au compilateur? Le runtime? Autre chose?
  • Dans quels autres scénarios (rares?) La trace de pile ne parvient-elle pas à capturer des informations essentielles comme celles-ci?
49
polygenelubricants

Ceci est normalement lié aux informations de débogage manquantes. Vous utilisez probablement JRE (pas JDK), qui n'inclut pas les informations de débogage pour les classes rt.jar. Essayez d'utiliser JDK complet, vous obtiendrez les emplacements appropriés dans la trace de la pile:

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

Notez que si vous utilisez Ant build et si l'attribut de débogage est défini sur false dans la commande javac, cela peut se produire.

ex: si vous avez besoin d'un emplacement correct dans le jeu de traces debug = true dans Ant build,

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

J'ai eu le même problème, j'utilise le ressort et Apache ant pour une intégration continue.

L'erreur que j'ai eue était dans le fichier build.xml.

Le journal des changements de genre avec un contenu plus précis était:

build.xml avec l'erreur:

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

build.xml sans erreur:

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

Au sein de la structure, je manquais de courage debug = "true"

6
jamlhet

J'ai exécuté le code dans Eclipse et j'ai obtenu la sortie suivante,

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)

Si vous incluez la source complète (à partir de JDK), vous pouvez réellement déboguer vers la ligne 177 dans String.Java

3
bragboy

Dans Eclipse: Préférences> Java> JRE installés. L'entrée vérifiée doit avoir un chemin à l'intérieur du JDK, par exemple C:\Program Files (x86)\Java\jdk1.7.0_55\jre.

1
Peter Tseng

Cela se produit lorsqu'il n'y a pas d'informations de débogage (ligne) dans la source ou lorsque VM est invité à jeter ces informations au moment du chargement de la classe. Puisque vous avez des numéros de ligne, ce n'est pas le paramètre VM mais la classe String manque des informations de débogage.

1
Aaron Digulla