È * mai * ok per catturare StackOverflowError in Java?

27

Ero solito pensare che non lo fosse, ma ieri dovevo farlo. Si tratta di un'applicazione che utilizza Akka (un'implementazione del sistema di attori per la JVM) per elaborare lavori asincroni. Uno degli attori esegue alcune manipolazioni di PDF e, poiché la libreria è bacata, muore con StackOverflowError di tanto in tanto.

Il secondo aspetto è che Akka è configurato per arrestare l'intero sistema degli attori se viene rilevato un errore fatale JVM (ad esempio StackOverflowError).

Il terzo aspetto è che questo sistema di attori è incorporato in un'app Web (per motivi WTF, legacy, motivi), quindi quando il sistema dell'attore viene chiuso, l'app web non lo è. L'effetto netto è che su una StackOverflowError la nostra applicazione di elaborazione dei lavori diventa solo un'app web vuota.

Come soluzione rapida ho dovuto rilevare il lancio di StackOverflowError , in modo che il pool di thread del sistema degli attori non venisse eliminato. Questo mi ha portato a pensare che forse a volte va bene catturare tali errori, specialmente in contesti come questo? Quando c'è un pool di thread che elabora attività arbitrarie? A differenza di OutOfMemoryError non riesco a immaginare come un StackOverflowError possa lasciare un'applicazione in uno stato incoerente. Lo stack viene cancellato dopo un tale errore, quindi il calcolo può continuare normalmente. Ma forse mi manca qualcosa di importante.

Inoltre, si noti che sono tutto per correggere l'errore in primo luogo (in effetti ho già risolto un SOE in questa stessa app qualche giorno fa), ma in realtà non lo faccio sapere quando potrebbe verificarsi questo tipo di situazione.

Perché sarebbe meglio riavviare il processo JVM invece di prendere il StackOverflowError , contrassegnarlo come fallito e continuare con la mia attività?

C'è qualche ragione convincente per non catturare mai gli SOE? Tranne "best practice", che è un termine vago che non mi dice nulla.

    
posta Ionuț G. Stan 22.08.2013 - 08:07
fonte

2 risposte

44

Come regola generale, se fosse assolutamente mai e poi mai accettabile a fare qualcosa, e ci fosse un accordo in merito, gli implementatori linguistici non l'avrebbero consentito. Non ci sono quasi massime così unanimemente definite. (Fortunatamente, perché è ciò che ci mantiene programmatori umani nei lavori!)

Sembra proprio che tu abbia trovato una situazione in cui catturare questo errore è l'opzione migliore per te: consente alla tua applicazione di funzionare, mentre tutte le altre alternative no, e questo è ciò che conta alla fine. Tutte le "migliori pratiche" sono semplicemente sommatorie di lunghe esperienze con molti casi che possono di solito essere usati al posto di un'analisi dettagliata di un caso specifico per risparmiare tempo; nel tuo caso, hai già fatto l'analisi specifica e ottenuto un risultato diverso. Congratulazioni, sei capace di pensare in modo indipendente!

(Ciò detto, sicuramente ci sono situazioni in cui un overflow dello stack potrebbe lasciare un'applicazione incoerente proprio come un esaurimento della memoria. Immagina solo che qualche oggetto sia costruito e poi inizializzato con l'aiuto di chiamate di metodo interne nidificate - se uno di questi genera , l'oggetto potrebbe benissimo trovarsi in uno stato che non dovrebbe essere possibile, proprio come se una allocazione fosse fallita, ma ciò non significa che la tua soluzione non potrebbe essere ancora la migliore.)

    
risposta data 22.08.2013 - 08:19
fonte
2

Non so se ci sono dei rischi specifici JVM qui, ma nel complesso sembra abbastanza ragionevole.

Per esempio ci sono algoritmi ricorsivi, come naive quicksort, che hanno log(n) di profondità dello stack in un caso tipico, ma nel peggiore dei casi degradano alla profondità n che può far esplodere lo stack.

Il caso peggiore è raro ed è improbabile che si verifichi di nuovo se si riavvia l'ordinamento sul set parzialmente ordinato, quindi ha molto senso rilevare l'eccezione di overflow dello stack quando succede e riavviare il lavoro invece di cercare di impedire l'errore da accadendo o uccidendo l'intera applicazione.

    
risposta data 04.09.2013 - 01:53
fonte

Leggi altre domande sui tag