He tenido instancias de nuestro código Java atrapar a NullPointerException
, pero cuando trato de registrar el StackTrace (que básicamente termina llamando Throwable.printStackTrace()
), todo lo que obtengo es:
java.lang.NullPointerException
¿Alguien más se ha encontrado con esto? Traté de buscar en Google "java null pointer empty stack trace" pero no encontré nada como esto.
java
nullpointerexception
Edward Shtern
fuente
fuente
-XX:-OmitStackTraceInFastThrow
en el dup: stackoverflow.com/questions/4659151/…Respuestas:
Probablemente esté utilizando el HotSpot JVM (originalmente de Sun Microsystems, luego comprado por Oracle, parte de OpenJDK), que realiza mucha optimización. Para recuperar los rastros de la pila, debe pasar la opción
-XX:-OmitStackTraceInFastThrow
a la JVM.La optimización es que cuando se produce una excepción (generalmente una NullPointerException) por primera vez, se imprime el seguimiento completo de la pila y la JVM recuerda el seguimiento de la pila (o tal vez solo la ubicación del código). Cuando esa excepción ocurre con suficiente frecuencia, el seguimiento de la pila ya no se imprime, tanto para lograr un mejor rendimiento como para no inundar el registro con trazas de pila idénticas.
Para ver cómo se implementa esto en HotSpot JVM, tome una copia y busque la variable global
OmitStackTraceInFastThrow
. La última vez que miré el código (en 2019), estaba en el archivo graphKit.cpp .fuente
-XX:-OmitStackTraceInFastThrow
bandera también. Todavía tengo que confirmar si esa fue la razón por la que tampoco estaba imprimiendo rastros de la pila (por ejemplo, usandoe.printStackTrace
), pero parece muy probable. He ampliado la respuesta para reflejar este descubrimiento.Como mencionaste en un comentario, estás usando log4j. Descubrí (sin darse cuenta) un lugar donde había escrito
en lugar del típico
por pereza o tal vez simplemente no pensar en ello La parte desafortunada de esto es que no se comporta como esperabas. La API del registrador realmente toma Object como primer argumento, no una cadena, y luego llama a toString () en el argumento. Entonces, en lugar de obtener el bonito y bonito seguimiento de la pila, simplemente imprime toString, que en el caso de NPE es bastante inútil.
¿Quizás esto es lo que estás experimentando?
fuente
Hemos visto este mismo comportamiento en el pasado. Resultó que, por alguna extraña razón, si ocurría una NullPointerException en el mismo lugar en el código varias veces, después de un tiempo, el uso
Log.error(String, Throwable)
dejaría de incluir rastros completos de la pila.Intenta mirar más atrás en tu registro. Puede encontrar al culpable.
EDITAR: este error suena relevante, pero se solucionó hace tanto tiempo que probablemente no sea la causa.
fuente
-XX:-OmitStackTraceInFastThrow
bandera JVM sugerida por Joshua? Consulte también stackoverflow.com/a/2070568/6198 .Aquí hay una explicación: Hotspot causó excepciones para perder sus rastros de pila en producción, y la solución
Lo he probado en Mac OS X
Máquina virtual de servidor Java HotSpot (TM) de 64 bits (compilación 20.1-b02-383, modo mixto)
Para este fragmento específico de código, 12288 iteraciones (¿+ frecuencia?) Parece ser el límite en el que JVM ha decidido utilizar una excepción preasignada ...
fuente
exception.toString
no te da el StackTrace, solo devuelveUse en su
exception.printStackTrace
lugar para generar el StackTrace.fuente
getStackTrace()
para asegurarte de que el problema no está en tu registrador?Sugerencia alternativa: si está utilizando Eclipse, puede establecer un punto de interrupción en NullPointerException (en la perspectiva de Depuración, vaya a la pestaña "Puntos de interrupción" y haga clic en el pequeño icono que tiene un!)
Marque las opciones "atrapado" y "no atrapado": ahora, cuando active el NPE, inmediatamente tendrá un punto de interrupción y podrá pasar y ver cómo se maneja exactamente y por qué no está obteniendo un seguimiento de la pila.
fuente
toString()
solo devuelve el nombre de la excepción y el mensaje opcional. Sugeriría llamarpara volcar el mensaje, o si necesita los detalles sangrientos:
fuente
(Su pregunta aún no está clara sobre si su código está llamando
printStackTrace()
o si lo está haciendo un controlador de registro).Aquí hay algunas explicaciones posibles sobre lo que podría estar sucediendo:
El registrador / manejador que se está utilizando se ha configurado para que solo muestre la cadena de mensaje de la excepción, no un seguimiento completo de la pila.
Su aplicación (o alguna biblioteca de terceros) está registrando la excepción utilizando en
LOG.error(ex);
lugar de la forma de 2 argumentos (por ejemplo) el método log4j Logger.El mensaje proviene de un lugar diferente de donde crees que está; por ejemplo, en realidad se trata de algún método de biblioteca de terceros, o algunas cosas aleatorias sobrantes de intentos anteriores de depuración.
La excepción que se está registrando ha sobrecargado algunos métodos para ocultar el seguimiento de la pila. Si ese es el caso, la excepción no será una NullPointerException genuina, sino que será un subtipo personalizado de NPE o incluso alguna excepción no conectada.
Creo que la última explicación posible es bastante improbable, pero la gente al menos contempla hacer este tipo de cosas para "prevenir" la ingeniería inversa. Por supuesto, solo realmente logra dificultar la vida de los desarrolladores honestos.
fuente
Cuando utiliza AspectJ en su proyecto, puede suceder que algún aspecto oculte su parte del seguimiento de la pila. Por ejemplo, hoy tuve:
Este rastro de la pila se imprimió al ejecutar la prueba a través de la prueba segura de Maven.
Por otro lado, al ejecutar la prueba en IntelliJ, se imprimió un seguimiento de pila diferente:
fuente
Esto generará la excepción, use solo para depurar, debería manejar mejor sus excepciones.
fuente