¿Por qué Java no te dice qué puntero es nulo?
debugging nullpointerexception (6)
Desafortunadamente, esta es la forma en que funciona Java.
Si este es el código "tuyo", simplemente agrega fragmentos como
if (foo == null) {
throw new NullPointerException("foo == null");
}
Justo después de asignar foo. Si foo es un parámetro, verifique inmediatamente al comienzo del cuerpo del método, y lance IllegalArgumentException en su lugar.
Esto debería ayudarte a aclarar las cosas.
Siempre me he preguntado por qué la JVM no le dice qué puntero (o más precisamente, qué variable) es nulo cuando se lanza una NullPointerException
.
Un número de línea no es lo suficientemente específico porque la línea infractora a menudo puede contener numerosas variables que podrían haber causado el error.
¿Hay algún indicador de compilador o JVM que haga que estos mensajes de excepción sean más útiles?
Es porque la falta de referencia siempre ocurre cuando no hay ningún nombre disponible. El valor se carga en la pila de operandos, y luego se pasa a uno de los códigos de operación de JRE que lo eliminan. Sin embargo, la pila de operandos no tiene un nombre para asociar con un valor nulo. Todo lo que tiene es ''nulo''. Con algún código de seguimiento de ejecución inteligente, se puede derivar un nombre, pero eso agregaría una sobrecarga con un valor limitado.
Debido a esto, no hay una opción JRE que active información adicional para las excepciones de puntero nulo.
En este ejemplo, la referencia se almacena en la ranura local 1, que se asigna a un nombre de variable local. Pero la desreferencia se produce en la instrucción invokevirtual, que solo ve un valor ''nulo'' en la pila, y luego lanza una excepción:
15 aload_1
16 invokevirtual #5
Igualmente válido sería una carga de matriz seguida de una desreferencia, pero en este caso no hay un nombre para asignar al valor ''nulo'', solo un índice fuera de otro valor.
76 aload 5
78 iconst_0
79 aaload
80 invokevirtual #5
Tampoco puede asignar los nombres de forma estática a cada instrucción: este ejemplo produce una gran cantidad de códigos de byte, pero puede ver que la instrucción de desreferenciación recibirá objA u objB, y deberá realizar un seguimiento dinámico para informar del correcto. como ambas variables fluyen a la misma instrucción de desreferenciación:
(myflag ? objA : objB).toString()
Puede agregar un punto de interrupción en la excepción de puntero nulo en Eclipse al depurar para obtener la causa exacta de la excepción.
Si
Un número de línea no es lo suficientemente específico porque la línea infractora a menudo puede contener numerosas variables que podrían haber causado el error.
entonces sugiero:
- Rompa esa línea en más de una línea y asigne los posibles valores de generación
NullPointerException
a las variables temporales. - Use un depurador y repase cada llamada de método hasta que encuentre la que causa el problema.
Si divide la línea en varias líneas en lugar de hacer varias llamadas de método en una línea, o si establece un punto de interrupción en esa línea y recorre la línea con un depurador, puede averiguar qué referencia es nula con bastante facilidad.
Una vez que haya JIT el código, es solo el puntero nativo matemático, y si cualquier puntero en el código nativo es nulo, se produce la excepción. Tendría un impacto devastador en el rendimiento revertir ese conjunto a la variable original, y considerando que el JIT optimiza el código generado a diferentes niveles, a menudo ni siquiera es posible.