NullPointerException en Java sin StackTrace

He tenido instancias de nuestro código Java capturar una NullPointerException , pero cuando bash registrar el StackTrace (que básicamente termina llamando a Throwable.printStackTrace() ), todo lo que obtengo es:

 java.lang.NullPointerException 

¿Alguien más se ha encontrado con esto? Intenté buscar en Google “rastro de stack vacía de puntero java” pero no encontré nada como esto.

Probablemente esté utilizando Sun JVM, que realiza una gran cantidad de optimización. Para recuperar los rests de stack, debe pasar la opción -XX:-OmitStackTraceInFastThrow a la JVM.

Las OpenJDK JVM modernas (¿1.8 y superiores?) Parecen aceptar también el -XX:-OmitStackTraceInFastThrow (y tienen activada la optimización del seguimiento de stack de forma predeterminada).

Como mencionaste en un comentario, estás usando log4j. Descubrí (inadvertidamente) un lugar donde había escrito

 LOG.error(exc); 

en lugar de lo típico

 LOG.error("Some informative message", e); 

a través de la pereza o tal vez simplemente sin pensar en ello. La parte desafortunada de esto es que no se comporta como esperabas. La API de registrador realmente toma Object como el primer argumento, no una cadena, y luego llama aString () en el argumento. Entonces, en lugar de obtener el bonito y bonito seguimiento de stack, simplemente imprime el toString, que en el caso de NPE es bastante inútil.

Quizás esto es lo que estás experimentando?

Hemos visto este mismo comportamiento en el pasado. Resultó que, por algún loco motivo, si una NullPointerException ocurría en el mismo lugar en el código varias veces, después de un tiempo usando Log.error(String, Throwable) dejaría de incluir rastros de stack completos.

Intente mirar más atrás en su registro. Puede encontrar al culpable.

EDITAR: este error suena relevante, pero fue corregido hace tanto tiempo que probablemente no sea la causa.

Aquí hay una explicación: el punto de acceso provocó que las excepciones pierdan sus trazas de stack en producción, y la solución

Lo he probado en Mac OS X

  • versión de java “1.6.0_26”
  • Java (TM) SE Runtime Environment (comstackción 1.6.0_26-b03-383-11A511)
  • Java HotSpot (TM) 64-Bit Server VM (comstackción 20.1-b02-383, modo mixto)

     Object string = "abcd"; int i = 0; while (i < 12289) { i++; try { Integer a = (Integer) string; } catch (Exception e) { e.printStackTrace(); } } 

Para este fragmento específico de código, 12288 iteraciones (¿+ frecuencia?) Parece ser el límite donde JVM ha decidido usar la excepción preasignada ...

exception.toString no le proporciona el StackTrace, solo devuelve

una breve descripción de esto arrojable. El resultado es la concatenación de:

 * the name of the class of this object * ": " (a colon and a space) * the result of invoking this object's getLocalizedMessage() method 

Use exception.printStackTrace lugar para generar el StackTrace.

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!)

Comprueba las opciones “capturadas” y “no detectadas”: ahora cuando disparas el NPE, de inmediato lo rompes y luego puedes ver cómo exactamente se maneja y por qué no estás obteniendo un rastro de stack.

toString() solo devuelve el nombre de la excepción y el mensaje opcional. Sugeriría llamar

 exception.printStackTrace() 

para volcar el mensaje, o si necesita los detalles sangrientos:

  StackTraceElement[] trace = exception.getStackTrace() 

(Su pregunta aún no está clara sobre si su código está llamando a printStackTrace() o si lo está haciendo un manejador de registros).

Aquí hay algunas explicaciones posibles sobre lo que podría estar pasando:

  • El registrador / controlador que se está utilizando se ha configurado para que solo muestre la cadena de mensajes de la excepción, no un seguimiento de stack completo.

  • Su aplicación (o una biblioteca de terceros) está registrando la excepción con LOG.error(ex); en lugar de la forma de 2 argumentos de (por ejemplo) el método Log4j Logger.

  • El mensaje viene de un lugar diferente al que crees que es; por ejemplo, en realidad viene algún método de biblioteca de terceros, o algunas cosas aleatorias sobrantes de bashs anteriores de depurar.

  • La excepción que se está registrando ha sobrecargado algunos métodos para oscurecer el stacktrace. 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 las personas al menos contemplan hacer este tipo de cosas para “prevenir” la ingeniería inversa. Por supuesto, solo tiene éxito al dificultar la vida de los desarrolladores honestos.

Esto generará la Excepción, use solo para depurar, debe manejar mejor sus excepciones.

 import java.io.PrintWriter; import java.io.StringWriter; public static String getStackTrace(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); t.printStackTrace(pw); pw.flush(); sw.flush(); return sw.toString(); } 

Cuando utiliza AspectJ en su proyecto, puede suceder que algún aspecto oculte su parte del seguimiento de la stack. Por ejemplo, hoy tuve:

 java.lang.NullPointerException: at com.company.product.MyTest.test(MyTest.java:37) 

Este rastro de stack se imprimió al ejecutar la prueba a través del fuego seguro de Maven.

Por otro lado, al ejecutar la prueba en IntelliJ, se imprimió un seguimiento de stack diferente:

 java.lang.NullPointerException at com.company.product.library.ArgumentChecker.nonNull(ArgumentChecker.java:67) at ... at com.company.product.aspects.CheckArgumentsAspect.wrap(CheckArgumentsAspect.java:82) at ... at com.company.product.MyTest.test(MyTest.java:37)