2013-10-23 18 views
9

Ho un arresto piuttosto complicato in Java: c'è un sacco di lavoro di pulizia da fare. In particolare sto cercando di capire come gestire l'errore da un thread di hookdown. Il mio codice include questo momento:Cosa succede se System.exit viene chiamato da un hook di chiusura?

try { 
    return shutdownPromise = doShutdown(); 
} 
catch (Throwable exc) { 
    logger.error("An exception was thrown while shutting down the application.", exc); 
    System.exit(1); 
    return null; 
} 

Quando ho originariamente scritto questo ho pensato essenzialmente, un errore di arresto dovrebbe solo andare dritto al exit. Ma exit non è così basso livello; chiama i ganci di arresto.

Così ho pensato -

  1. Cosa chiamando l'uscita da un gancio di arresto fare?
  2. Qual è il modo corretto di gestire l'errore da un hook di chiusura?
+4

@libik Perché no? Questo è in realtà incoraggiato, per condividere la conoscenza. In effetti, c'è una casella di controllo che dice specificamente "rispondi alla tua domanda". – Doorknob

+0

È una bella risposta; vale un valore. – Bathsheba

+1

Beh, sì, ma se davvero fai la domanda e la capisci da sola o con l'aiuto degli altri ... Non fare domande e rispondere prima che qualcuno abbia una risposta. – libik

risposta

19

In primo luogo, la risposta facile: il processo si blocca.

System.exit snoda per chiamare Shutdown.exit, che termina con this code block:

synchronized (Shutdown.class) { 
    /* Synchronize on the class object, causing any other thread 
     * that attempts to initiate shutdown to stall indefinitely 
     */ 
    sequence(); 
    halt(status); 
} 

Il commento è completamente accurato. Ma per capire questo dobbiamo vedere esattamente cosa fa l'hook di shutdown.

I ganci di arresto vengono aggiunti tramite ApplicationShutdownHooks.add, come spiegato in this answer here. Si noti che il metodo di cui sopra sequence casualmente finisce sul this line of code in Shutdown.runHooks:

if (hook != null) hook.run(); 

Innanzitutto, occorre notare questi ganci sono non tua applicazione ganci di arresto. Si tratta di hook di arresto del sistema, che sono diversi e uno di loro è responsabile per l'esecuzione degli hook di arresto dell'applicazione. Si noti che è eseguito, non start. In altre parole, è blocchi. Uno di questi hook di shutdown sarà un hook di sistema che avvia contemporaneamente tutti i hook di shutdown dell'applicazione (è possibile tracciare questo codice per se stessi o nella risposta collegata), quindi blocca fino a quando non si completa con una chiamata Thread.join. Uno di questi sarà il gancio di arresto dell'applicazione, che, se chiama System.exit, attenderà per ottenere il blocco su Shutdown.class per sempre.

Quindi, la risposta stupida: chiamare invece Runtime.getRuntime().halt(). Dico "la risposta stupida" perché questa è probabilmente la cosa di livello leggermente più basso che stavi cercando di fare invece di uscire. Se System.exit rappresenta un arresto pulito che non è riuscito, quindi halt è un arresto forzato che avrà sempre esito positivo.

Successivamente, la risposta più intelligente: probabilmente nulla. Lascia che il tuo gancio di chiusura finisca, per i seguenti motivi. Il tuo hook di shutdown non è proprietario dell'arresto - in particolare, potrebbero esserci altri hook di shutdown che devono fare il loro lavoro. Al contrario, sospetto che una delle responsabilità di questo hook sia di forzare un hard shutdown alla fine. Consiglierei di crearlo come attività ritardata immediatamente, quindi scrivere questo hook normalmente.

Problemi correlati