Traccia dello stack NullPointerException non disponibile senza agente di debug

Recentemente ho trovato un bug che causa una NullPointerException. L’eccezione viene rilevata e registrata utilizzando un’istruzione standard slf4j. Codice abbreviato di seguito:

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

Come puoi vedere, niente di speciale. Tuttavia, di tutte le dichiarazioni di registrazione delle eccezioni che abbiamo, solo questa non stampa una traccia dello stack. Tutto ciò che stampa è il messaggio (rappresentato come “…”) e il nome della class di eccezione (java.lang.NullPointerException).

Dal momento che la traccia dello stack su un’eccezione è lazy loaded, ho pensato che potrebbe esserci un problema di riordino delle istruzioni di qualche tipo e ho deciso di chiamare e.getStackTrace () prima dell’istruzione del log. Questo non ha fatto differenza.

Così ho deciso di riavviare con l’agente di debug abilitato. Tuttavia, poiché mi sono persino collegato al processo, ho notato che ora le tracce dello stack stavano stampando. Quindi, chiaramente la presenza dell’agente di debug ha reso disponibili alcune informazioni di debug aggiuntive.

Da allora ho risolto la causa principale dell’eccezione. Ma vorrei sapere perché la traccia dello stack non era disponibile senza un debugger. Qualcuno sa?

Chiarimento: questo non è un problema di registrazione . Immagina la stessa clausola try / catch, ma nel trucco, stampo il valore di:

 e.getStackTrace().length 

Senza un debugger stampa ‘0’, con un debugger stampa un numero positivo (9 in questo caso).

Maggiori informazioni: questo sta accadendo su JDK 1.6.0_13, 64bit, amd64, linux 2.6.9

È ansible che questo codice sia in un loop interno? Quindi il compilatore JIT potrebbe compilare lo stack di chiamate per questo codice nativo, perdendo le informazioni sullo stack. Quindi quando si collega il debugger si disabilita il JIT, rendendo nuovamente disponibili le informazioni.

Le altre eccezioni manuali continuano a visualizzare le informazioni poiché il JIT non sta ottimizzando.

Sembra che a volte questo possa accadere per altri da un commento in questo codice sorgente di class alla riga 102:

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

Con il flag JVM -XX: -OmitStackTraceInFastThrow è ansible disabilitare l’ottimizzazione delle prestazioni della JVM per questo caso d’uso. Se questo parametro è dato, che disabilita il flag, lo stacktrace sarà disponibile.

Per maggiori informazioni si prega di dare un’occhiata alle seguenti note di rilascio:

“Il compilatore nella VM del server ora fornisce gli stack backtrace corretti per tutte le eccezioni built-in” fredde “.Per le prestazioni, quando tale eccezione viene lanciata alcune volte, il metodo può essere ricompilato. Dopo la ricompilazione, il compilatore può scegliere un tattica più veloce utilizzando eccezioni preallocate che non forniscono una traccia di stack Per disabilitare completamente l’utilizzo di eccezioni preallocate, utilizzare questo nuovo flag: -XX: -OmitStackTraceInFastThrow. ” http://java.sun.com/j2se/1.5.0/relnotes.html

Posso replicare questo, ma sembra strano che questo stia accadendo nella tua Azione da qualche parte.

Se si chiama setStackTrace con un array vuoto, ciò causerà la visualizzazione del solo testo.

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

Eseguendolo ….

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