Quand je reçois un NPE, je vais obtenir une trace de la pile avec le numéro de ligne. Ce est utile, mais si la ligne est très dense et/ou contient l'expression imbriquées, il est encore impossible de savoir quelle référence était nulle.Est-il possible de retrouver l'expression qui a provoqué une NPE?
Certes, cette information a dû être disponible quelque part. Est-il possible de comprendre cela? (Si ce n'est pas l'expression java, alors au moins l'instruction bytecode qui a causé NPE serait utile aussi)
Édition 1: J'ai vu quelques commentaires suggérant de briser la ligne, etc., ce qui, sans vouloir offenser, est vraiment non-constructif et non pertinent. Si je pouvais le faire, j'aurais! Disons simplement que modifier la source est hors de question. Edit # 2: apangin a posté une excellente réponse ci-dessous, que j'ai acceptée. Mais c'est SOOO COOL que j'ai dû inclure la sortie ici pour tous ceux qui ne veulent pas l'essayer eux-mêmes! ;)
suppose donc que j'ai ce programme pilote TestNPE.java
1 public class TestNPE {
2 public static void main(String[] args) {
3 int n = 0;
4 String st = null;
5
6 System.out.println("about to throw NPE");
7 if (n >= 0 && st.isEmpty()){
8 System.out.println("empty");
9 }
10 else {
11 System.out.println("othereise");
12 }
13 }
14
15 }
Le bytecode ressemble à ceci (montrant que la principale() méthode et en omettant d'autres parties non pertinentes)
Code:
stack=2, locals=3, args_size=1
0: iconst_0
1: istore_1
2: aconst_null
3: astore_2
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #3 // String about to throw NPE
9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: iload_1
13: iflt 34
16: aload_2
17: invokevirtual #5 // Method java/lang/String.isEmpty:()Z
20: ifeq 34
23: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
26: ldc #6 // String empty
28: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
31: goto 42
34: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
37: ldc #7 // String othereise
39: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
42: return
maintenant Lorsque vous exécutez le pilote TestNPE avec l'agent, vous obtenez ce
$ java -agentpath:libRichNPE.o TestNPE
about to throw NPE
Exception in thread "main" java.lang.NullPointerException: location=17
at TestNPE.main(TestNPE.java:7)
l'invokevirtual # 5 à l'offset 17! Juste COMMENT COOL EST-CE QUE C'EST?
Bonne question, mais aussi garder à l'esprit que si la ligne est dense la la qualité du code est probablement moins qu'optimale. – Kayaman
Je sais que vous ne pouvez pas obtenir le numéro de colonne ... mais si vous pouvez utiliser les retours pour interrompre les appels sur cette ligne vers une série de lignes 'Java' affichera le numéro de ligne concerné tout en le traitant comme une ligne. –
Cela dépend de l'implémentation de la machine virtuelle Java. Par exemple, SAP JVM imprime le nom de champ null dans le message d'exception. –