Question

Je me suis toujours demandé pourquoi la machine virtuelle Java ne vous dit pas qui pointeur (ou plus précisément, quelle variable) est nulle lorsqu'une NullPointerException est levée.

Un numéro de ligne ne suffit pas spécifique parce que la ligne incriminée peut contenir souvent de nombreuses variables qui pourraient avoir causé l'erreur.

Y at-il compilateur ou drapeau JVM qui rendrait ces messages d'exception plus utile?

Était-ce utile?

La solution

Il est parce que le déréférencement arrive toujours quand il n'y a pas de nom disponible. La valeur est chargée sur la pile d'opérandes, et est ensuite transmis à l'un des opcodes JRE que déréférences il. Cependant, la pile d'opérandes n'a pas de nom à associer à une valeur nulle. Tout ce qu'il a est « nul ». Avec un code de suivi d'exécution intelligent, un nom peut être dérivé, mais cela ajouterait les frais généraux d'une valeur limitée.

En raison de cela, il n'y a pas d'option de JRE qui actionnera des informations supplémentaires pour les exceptions de pointeur nul.

Dans cet exemple, la référence est stockée dans l'emplacement local 1, qui correspond à un nom de variable locale. Mais le déréférencement arrive dans l'instruction invokevirtual, qui ne voit qu'une valeur « nulle » sur la pile, et jette une exception:

15 aload_1
16 invokevirtual #5 

De même valable serait une charge de tableau, suivi d'un déréférencement, mais dans ce cas, il n'y a pas de nom à la carte à la valeur « null », juste un indice hors d'une autre valeur.

76 aload    5
78 iconst_0
79 aaload
80 invokevirtual #5

Vous ne pouvez pas attribuer les noms statiquement à chaque instruction soit - cet exemple produit beaucoup de bytecode, mais vous pouvez voir que l'instruction de déréférencement recevra objA ou objB, et vous devez suivre cette dynamique pour signaler la une droite, comme les deux variables de flux à la même instruction de déréférencement:

(myflag ? objA : objB).toString()

Autres conseils

Une fois que vous Jit le code, il est juste mathématiques de pointeur natif, et si l'un pointeur dans le code natif est nulle, il jette l'exception. Il aurait un impact sur les performances dévastatrices pour inverser cette assemblée de retour à la variable d'origine, et compte tenu du JIT permet d'optimiser le code généré à différents niveaux, est souvent même pas possible.

Si vous cassez la ligne en plusieurs lignes au lieu de faire plusieurs appels de méthode sur une ligne, ou si vous définissez un point d'arrêt sur cette ligne et franchissez la ligne avec un débogueur, vous pouvez comprendre que la référence est nul assez facilement.

Si

  

Un numéro de ligne ne suffit pas spécifique   parce que la ligne incriminée peut souvent   contiennent de nombreuses variables qui pourraient   ont provoqué l'erreur.

alors je suggère:

  1. La rupture de cette ligne dans plus d'une ligne et affecter les valeurs de NullPointerException génératrices possibles pour les variables temporaires.
  2. Utilisez un débogueur et l'étape sur chaque appel de méthode jusqu'à ce que vous trouviez celui qui cause le problème.

Ceci est malheureusement juste la façon dont fonctionne Java.

Si cela est « votre » code, puis ajoutez simplement des extraits comme

if (foo == null) {
  throw new NullPointerException("foo == null");
}

juste après l'attribution foo. Si foo est un paramètre puis vérifiez immédiatement au début du corps de la méthode, et jeter IllegalArgumentException à la place.

Cela devrait vous aider à clarifier les choses.

Vous pouvez ajouter un point d'arrêt à l'exception de pointeur NULL dans Eclipse lors du débogage pour obtenir la cause exacte de l'exception.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top