Quando si cattura java.lang.Error?

In quali situazioni si dovrebbe catturare java.lang.Error su un’applicazione?

In generale, mai. Tuttavia, a volte è necessario rilevare errori specifici.

Se stai scrivendo codice framework-ish (caricamento di classi di terze parti), potrebbe essere saggio prendere LinkageErrors (nessuna class def trovata, link insoddisfatto, cambiamento di class incompatibile). Ho anche visto alcuni stupidi codici di terze parti che lanciano sublcass di errori, quindi dovrai gestirli entrambi.

A proposito, non sono sicuro che non sia ansible recuperare da OutOfMemory.

Mai. Non si può mai essere sicuri che l’applicazione sia in grado di eseguire la prossima riga di codice. Se ottieni un OutOfMemoryError , non hai la garanzia che sarai in grado di fare qualcosa in modo affidabile . Catch RuntimeException e controllato Eccezioni, ma mai Errori.

http://pmd.sourceforge.net/rules/strictexception.html

Generalmente si dovrebbe sempre catturare java.lang.Error e scriverlo in un log o visualizzarlo all’utente. Lavoro a supporto e vedo quotidianamente che i programmatori non possono dire cosa è successo in un programma.

Se si dispone di un thread daemon, è necessario impedirne la chiusura. In altri casi la tua applicazione funzionerà correttamente.

Dovresti solo catturare java.lang.Error al più alto livello.

Se guardi l’elenco degli errori, vedrai che la maggior parte può essere gestita. Ad esempio un ZipError verifica sulla lettura di file zip corrotti.

Gli errori più comuni sono OutOfMemoryError e NoClassDefFoundError , che sono entrambi nella maggior parte dei casi problemi di runtime.

Per esempio:

 int length = Integer.parseInt(xyz); byte[] buffer = new byte[length]; 

può produrre un OutOfMemoryError ma è un problema di runtime e nessun motivo per terminare il programma.

NoClassDefFoundError verifica principalmente se una libreria non è presente o se si lavora con un’altra versione di Java. Se è una parte facoltativa del tuo programma, allora non dovresti interrompere il tuo programma.

Posso dare molti altri esempi del perché sia ​​una buona idea catturare Throwable al livello più alto e produrre un utile messaggio di errore.

Nell’ambiente multithread, molto spesso lo vuoi catturare! Quando lo prendi, loggalo e termina l’intera applicazione! Se non lo fai, qualche thread che potrebbe fare parte cruciale sarebbe morto, e il resto dell’applicazione penserà che tutto sia normale. Al di fuori di ciò, possono accadere molte situazioni indesiderate. Un piccolo problema è che non sarebbe ansible trovare facilmente la radice del problema, se altri thread iniziano a generare eccezioni a causa di un thread che non funziona.

Ad esempio, di solito il ciclo dovrebbe essere:

 try { while (shouldRun()) { doSomething(); } } catch (Throwable t) { log(t); stop(); System.exit(1); } 

Anche in alcuni casi, vorresti gestire diversi Errori in modo diverso, ad esempio, su OutOfMemoryError potresti chiudere l’applicazione regolarmente (magari magari liberare della memoria e continuare), su altri, non c’è molto che tu possa fare.

Molto raramente.

Direi solo al livello più alto di un thread per TENTARE di emettere un messaggio con il motivo per cui un thread sta morendo.

Se ti trovi in ​​una struttura che fa questo genere di cose per te, lasciala al framework.

Quasi mai. Gli errori sono progettati per essere problemi di cui generalmente le applicazioni non possono fare nulla. L’unica eccezione potrebbe essere quella di gestire la presentazione dell’errore, ma anche questo potrebbe non andare come previsto a seconda dell’errore.

Di solito un Error non deve essere rilevato , poiché indica una condizione anomala che non dovrebbe mai verificarsi .

Dalla specifica dell’API Java per la class Error :

Un Error è una sottoclass di Throwable che indica i problemi seri che un’applicazione ragionevole non dovrebbe provare a catturare. La maggior parte di tali errori sono condizioni anormali. […]

Non è richiesto un metodo per dichiarare nella sua clausola di derivazione alcuna sottoclass di Errore che potrebbe essere generata durante l’esecuzione del metodo ma non rilevata, poiché questi errori sono condizioni anomale che non dovrebbero mai verificarsi.

Come menziona la specifica, un Error viene emesso solo in circostanze che sono le probabilità che, quando si verifica un Error , l’applicazione possa fare ben poco e, in alcune circostanze, la Java Virtual Machine stessa potrebbe trovarsi in uno stato instabile (come VirtualMachineError )

Sebbene un Error sia una sottoclass di Throwable che significa che può essere catturato da una clausola try-catch , ma probabilmente non è realmente necessaria, poiché l’applicazione si troverà in uno stato anormale quando viene lanciato un Error dalla JVM.

C’è anche una breve sezione su questo argomento nella Sezione 11.5 La gerarchia delle eccezioni delle specifiche della lingua Java, 2a edizione .

Se sei abbastanza pazzo da creare un nuovo framework di test di unità, il tuo runner di test probabilmente avrà bisogno di catturare java.lang.AssertionError lanciato da qualsiasi caso di test.

Altrimenti, vedi altre risposte.

E ci sono un paio di altri casi in cui se si cattura un errore, è necessario ricrearlo . Ad esempio ThreadDeath non dovrebbe mai essere catturato, può causare grossi problemi se lo si cattura in un ambiente contenuto (ad esempio un server di applicazioni):

Un’applicazione deve rilevare istanze di questa class solo se deve essere ripulita dopo essere stata terminata in modo asincrono. Se ThreadDeath viene catturato da un metodo, è importante che venga retrocesso in modo che il thread muoia effettivamente.

Molto, molto raramente.

L’ho fatto solo per casi molto specifici. Ad esempio, java.lang.UnsatisfiedLinkError potrebbe essere lanciato se due Independent ClassLoader caricano la stessa DLL. (Sono d’accordo sul fatto che dovrei spostare il JAR su un classloader condiviso)

Ma il caso più comune è che è necessario il login per sapere cosa è successo quando l’utente viene a lamentarsi. Vuoi un messaggio o un popup per l’utente, piuttosto che silenziosamente morto.

Anche i programmatori in C / C ++, visualizzano un errore e dicono qualcosa che le persone non capiscono prima di uscire (ad es. Errore di memoria).

In un’applicazione Android sto rilevando un java.lang.VerifyError . Una libreria che sto usando non funzionerà in dispositivi con una vecchia versione del sistema operativo e il codice della libreria genererà un tale errore. Ovviamente potrei evitare l’errore controllando la versione del sistema operativo in fase di runtime, ma:

  • L’SDK più vecchio supportato potrebbe cambiare in futuro per la libreria specifica
  • Il blocco errori try-catch fa parte di un meccanismo di ripiegamento più ampio. Alcuni dispositivi specifici, sebbene suppongano di supportare la libreria, generano eccezioni. Prendo VerifyError e tutte le eccezioni per utilizzare una soluzione di ripiego.

è abbastanza comodo catturare java.lang.AssertionError in un ambiente di test …

Idealmente non dovremmo gestire / catturare errori. Ma ci possono essere casi in cui dobbiamo fare, in base ai requisiti del quadro o dell’applicazione. Supponiamo di avere un demone XML Parser che implementa DOM Parser che consuma più memoria. Se c’è un requisito come il thread Parser non dovrebbe essere morto quando ottiene OutOfMemoryError , invece dovrebbe gestirlo e inviare un messaggio / posta all’amministratore dell’applicazione / framework.

idealmente non dovremmo mai rilevare errori nella nostra applicazione Java in quanto è una condizione anormale. L’applicazione si troverebbe in uno stato anormale e potrebbe causare problemi di messa in servizio o risultati errati.

Potrebbe essere appropriato rilevare errori nei test unitari che verificano l’asserzione. Se qualcuno distriggers le asserzioni o altrimenti cancella l’asserzione che vorresti sapere

C’è un errore quando la JVM non funziona più come previsto, o è sul punto di farlo. Se riscontri un errore, non c’è alcuna garanzia che il blocco catch venga eseguito, e ancor meno che funzioni fino alla fine.

Dipenderà anche dal computer in esecuzione, dallo stato attuale della memoria, quindi non c’è modo di testare, provare e fare del tuo meglio. Avrai solo un risultato insignificante.

Potrai anche declassare la leggibilità del tuo codice.