Pergunta

Recentemente encontrado um bug que provoca uma NullPointerException. A exceção é detectada e registrada usando uma instrução slf4j padrão. código abreviado abaixo:

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

Como você pode ver, nada extravagante. No entanto, de todas as declarações de registro a exceção de que nós temos, apenas um presente não imprime um rastreamento de pilha. Tudo o que imprime é a mensagem (representado como "...") e o nome da classe de exceção (Java.lang.NullPointerException).

Uma vez que o rastreamento de pilha em uma exceção é preguiçoso carregado, eu pensei que talvez haja uma instrução reordenação questão de algum tipo e decidiu chamar e.getStackTrace () antes de a declaração de registro. Este não fez diferença.

Então eu decidi reiniciar com o agente de depuração habilitada. No entanto, porque eu mesmo anexado ao processo, notei que agora os rastreamentos de pilha estava imprimindo. Então, claramente, a presença do agente de depuração causado alguma informação de depuração adicional para se tornar disponível.

Eu tenho desde então fixa a causa da exceção. Mas eu gostaria de saber por que o rastreamento de pilha não estava disponível sem um depurador. Alguém sabe?

Esclarecimento: isso não é uma questão de registro . Imagine a mesma cláusula try / catch, mas na captura, eu imprimir o valor de:

e.getStackTrace().length

Sem um depurador este imprime '0', com um depurador que imprime um número positivo (9 neste caso).

Mais informações: isso está acontecendo no JDK 1.6.0_13, 64bit, amd64, linux 2.6.9

Foi útil?

Solução

É possível que este código está em um loop interno? Em seguida, em seguida, o compilador JIT pode ser compilar a pilha de chamadas para que este código nativo, perdendo as informações de pilha. Então, quando você anexar o depurador ele desabilita o JIT, tornando a informação disponível novamente.

As outras exceções manuais manter exibir as informações como o JIT não está otimizando.

Parece que às vezes isso pode acontecer para os outros a partir de um comentário neste código-fonte da classe na linha 102:

http: //logging.apache. org / log4j / 1,2 / refex / org / Apache / log4j / SPI / LocationInfo.html

Outras dicas

Com a JVM bandeira XX: -OmitStackTraceInFastThrow você pode desativar a otimização da JVM desempenho para este caso de uso. Se este parâmetro é dado, que desativa a bandeira, o stacktrace estarão disponíveis.

Para mais informações por favor dê uma olhada nas notas após libertação:

"O compilador no servidor VM oferece agora backtraces de pilha corretas para todos 'frio' built-in exceções. Para efeitos de desempenho, quando tal exceção é lançada algumas vezes, o método pode ser recompilados. Depois de recompilação, o compilador . pode escolher um mais rápido tática usando exceções pré-alocados que não fornecem um rastreamento de pilha Para desativar completamente o uso de exceções pré-alocados, use esta nova bandeira: -XX: -OmitStackTraceInFastThrow ". http://java.sun.com/j2se/1.5.0/relnotes.html

Eu posso replicar este, mas parece um pouco estranho que isso estaria acontecendo em seu lugar Acção.

Se você chamar setStackTrace com um conjunto vazio, que vai causar apenas o texto a ser mostrado.

 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;
     }
 }

Executá-lo ....

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

% java Fark nothing
java.lang.NullPointerException
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top