Domanda Cosa succede se System.exit viene chiamato da un hook di chiusura?


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 al momento:

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 in shutdown dovrebbe andare dritto a exit. Ma exit non è un livello così basso; chiama i ganci di arresto.

Così ho pensato

  1. Cosa fa la chiamata all'uscita da un hook di chiusura?
  2. Qual è il modo corretto di gestire l'errore da un hook di chiusura?

10
2017-10-23 21:11


origine


risposte:


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

System.exit termina la chiamata Shutdown.exit, che termina con questo blocco di codice:

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 sono aggiunti tramite ApplicationShutdownHooks.add, come spiegato in questa risposta qui. Si noti che il sequence il metodo sopra finisce alla fine questa linea di codice in Shutdown.runHooks:

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

Innanzitutto, nota questi ganci non i ganci di arresto dell'applicazione. 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 è correreno inizio. In altre parole, blocchi. Uno di questi hook di shutdown sarà un hook di sistema che avvia simultaneamente tutti i hook di shutdown dell'applicazione (puoi tracciare questo codice per te stesso o nella risposta collegata), quindi blocca fino a quando non tutti completano l'utilizzo di un Thread.join chiamata. Uno di questi sarà il gancio di arresto dell'applicazione - che, se chiama System.exit, aspetterò di ottenere il blocco Shutdown.class per sempre.

Quindi, la risposta stupida: chiama Runtime.getRuntime().halt() anziché. 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 successo immediatamente.

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.


19
2017-10-23 21:11