Pregunta sobre stack-trace, java, logging, nullpointerexception – El seguimiento de la pila NullPointerException no está disponible sin el agente de depuración

58

Recientemente he encontrado un error que causa una excepción NullPointerException. La excepción se captura y se registra mediante una instrucción slf4j estándar. Código abreviado a continuación:

for(Action action : actions.getActions()) {
    try {
        context = action.execute(context);
    } catch (Exception e) {
        logger.error("...", e);
        break;
    }
}

Como puedes ver, nada de lujos. Sin embargo, de todas las declaraciones de registro de excepciones que tenemos, solo esta no imprime un seguimiento de pila. Todo lo que se imprime es el mensaje (representado como "...") y el nombre de la clase de excepción (java.lang.NullPointerException).

Dado que el seguimiento de la pila en una excepción está cargado de forma perezosa, pensé que tal vez hay un problema de reordenación de instrucciones de algún tipo y decidí llamar a e.getStackTrace () antes de la declaración de registro. Esto no hizo ninguna diferencia.

Así que decidí reiniciar con el agente de depuración habilitado. Sin embargo, debido a que incluso me vinculé al proceso, noté que ahora se estaban imprimiendo los rastros de la pila. Así que claramente la presencia del agente de depuración causó que cierta información de depuración adicional estuviera disponible.

Desde entonces he arreglado la causa raíz de la excepción. Pero me gustaría saber por qué el seguimiento de pila no estaba disponible sin un depurador. ¿Nadie sabe?

Aclaración:Esto no es un problema de registro. Imagine la misma cláusula try / catch, pero en el catch, imprimo el valor de:

e.getStackTrace().length

Sin un depurador, esto imprime '0', con un depurador imprime un número positivo (9 en este caso).

Más información: esto está sucediendo en JDK 1.6.0_13, 64bit, amd64, linux 2.6.9

posible duplicado deNullPointerException en Java sin StackTrace Christian
Trate de registrar las acciones, para que pueda tener una idea de qué acción causa esto. David Rabinowitz
Gracias por esta pregunta (y la solución)! Acabo de recibir esto como un informe de error para mi aplicación de registro y casi me estoy volviendo loco ... porque hayestaba No hay error en mi código. Esto aclaró las cosas bastante. Huxi
que vm estas usando ese comportamiento suenamuy extraño. Michael Wiles

Tu respuesta

3   la respuesta
88

Con el indicador JVM -XX: -OmitStackTraceInFastThrow puede deshabilitar la optimización del rendimiento de la JVM para este caso de uso. Si se da este parámetro, que desactiva la bandera, el seguimiento de pila estará disponible.

Para obtener más información, consulte las siguientes notas de la versión:

"El compilador en la máquina virtual del servidor ahora proporciona los registros de pila correctos para todas las excepciones integradas" frías ". Para propósitos de rendimiento, cuando se lanza una excepción de este tipo varias veces, el método puede ser recompilado. táctica más rápida que usa excepciones preasignadas que no proporcionan un seguimiento de la pila. Para deshabilitar completamente el uso de las excepciones preasignadas, use este nuevo indicador: -XX: -OmitStackTraceInFastThrow ".http://java.sun.com/j2se/1.5.0/relnotes.html

Tuvimos el mismo problema nuevamente e intentamos esta opción, y funcionó muy bien, mucho mejor que apagar el JIT completamente. ¡Gracias! omerkudat
Esto es muy interesante, gracias por señalarlo. omerkudat
¡Gracias por señalar esto! Daniel
19

¿Es posible que este código esté en un bucle interno? Luego, el compilador JIT podría estar compilando la pila de llamadas para este código nativo, perdiendo la información de la pila. Luego, cuando adjunta el depurador, desactiva el JIT, haciendo que la información vuelva a estar disponible.

Las otras excepciones manuales siguen mostrando la información ya que el JIT no está optimizando.

Parece que esto puede suceder a veces para otros a partir de un comentario en este código fuente de clase en la línea 102:

http://logging.apache.org/log4j/1.2/xref/org/apache/log4j/spi/LocationInfo.html

Más tarde, logré confirmar que al desactivar el JIT (JAVA_COMPILER = falso) hace que el seguimiento completo de la pila esté disponible cada vez que se produce esta excepción. omerkudat
0

Puedo replicar esto pero parece un poco extraño que esto suceda en tu Acción en algún lugar.

Si llama a setStackTrace con una matriz vacía, eso hará que solo se muestre el texto.

 public class Fark {
   public static void main(String[] args) {
       try {
           Fark.throwMe(args.length != 0);

       }
       catch (Exception e) {
           e.printStackTrace();
       }

   }

     public static final void throwMe(boolean arg) throws Exception{
         Exception e = new NullPointerException();
         if (arg) {
           e.setStackTrace(new StackTraceElement[0]);
         }
         throw e;
     }
 }

Ejecutandolo ....

% java Fark
java.lang.NullPointerException
        at Fark.throwMe(Fark.java:15)
        at Fark.main(Fark.java:5)

% java Fark nothing
java.lang.NullPointerException
¿Ocurre lo mismo si solo lanzas una NullPointerException en el intento? seth
Sí, el mismo comportamiento si me tiro manualmente. Y esto sucede solo en este try / catch. En otros donde lanzo manualmente, obtengo un comportamiento normal (es decir, pila completa). omerkudat
Sí, alguien mencionó esto también. Este no es el caso. omerkudat

Preguntas relacionadas