
Σε ποιες περιπτώσεις θα πρέπει κάποιος να πιάσει `java.lang.Error`σε μια εφαρμογή;

 
Πότε να πιάσει java.lang.Error;
===============================



Σε γενικές γραμμές, ποτέ. Ωστόσο, μερικές φορές χρειάζεται να πιάσει συγκεκριμένα σφάλματα.


Εάν γράφετε κώδικα πλαισίου-ish (φόρτωση τάξεις 3ο μέρος), θα ήταν ίσως συνετό να πιάσει LinkageErrors (καμία κατηγορία def βρεθεί, ανικανοποίητη σύνδεσμο, ασυμβίβαστη αλλαγή κατηγορίας). Επίσης έχω δει κάποια ηλίθια κωδικό 3ου μέρους ρίχνουν sublcasses από τα λάθη, έτσι θα πρέπει να χειριστούν αυτά είτε.


Με την ευκαιρία, δεν είμαι σίγουρος ότι δεν είναι δυνατόν να ανακάμψει από OutOfMemory.

 

Ποτέ. Ποτέ δεν μπορεί να είναι σίγουρος ότι η εφαρμογή είναι σε θέση να εκτελέσει την επόμενη γραμμή κώδικα. Εάν έχετε ένα `OutOfMemoryError`, έχετε [καμία εγγύηση ότι θα είστε σε θέση να κάνει τίποτα με αξιοπιστία](https://stackoverflow.com/a/8729011/545127) . Πιάσε RuntimeException και ελέγχονται εξαιρέσεις, αλλά ποτέ δεν τα λάθη.


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

 

Σε γενικές γραμμές θα πρέπει πάντα να πιάσει `java.lang.Error`και να το γράψετε σε ένα ημερολόγιο ή να το εμφανίσετε στο χρήστη. Δουλεύω για την υποστήριξη και βλέπουμε καθημερινά ότι οι προγραμματιστές δεν μπορεί να πει ό, τι έχει συμβεί σε ένα πρόγραμμα.


Εάν έχετε ένα νήμα δαίμονα, τότε πρέπει να το αποτρέψει να τερματιστεί. Σε άλλες περιπτώσεις η αίτησή σας θα λειτουργήσει σωστά.


Θα πρέπει να πιάσει μόνο `java.lang.Error`στο υψηλότερο επίπεδο.


Αν κοιτάξετε τη λίστα των σφαλμάτων θα δείτε ότι οι περισσότεροι μπορούν να αντιμετωπιστούν. Για παράδειγμα `ZipError`συμβαίνει στην ανάγνωση διεφθαρμένα αρχεία zip.


Τα πιο συνηθισμένα λάθη είναι `OutOfMemoryError`και `NoClassDefFoundError`, τα οποία είναι και τα δύο σε περισσότερα προβλήματα περιπτώσεις εκτέλεσης.


Για παράδειγμα:



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

```

μπορεί να παράγει ένα `OutOfMemoryError`, αλλά είναι ένα πρόβλημα χρόνου εκτέλεσης και δεν υπάρχει λόγος να τερματίσει το πρόγραμμά σας.


`NoClassDefFoundError`εμφανίζονται κυρίως αν μια βιβλιοθήκη δεν υπάρχει ή εάν εργάζεστε με μια άλλη εκδοχή της Java. Αν είναι ένα προαιρετικό μέρος του προγράμματος σας, τότε δεν θα πρέπει να τερματίσει το πρόγραμμά σας.


Μπορώ να δώσω πολλά ακόμη παραδείγματα γι 'αυτό είναι μια καλή ιδέα για να πιάσει `Throwable`σε κορυφαίο επίπεδο και να παράγει ένα χρήσιμο μήνυμα σφάλματος.

 

Σε multi-threaded περιβάλλον, που τις περισσότερες φορές θέλετε να το πιάσει! Όταν το πιάσει, να συνδεθείτε και να καταγγείλει ολόκληρη την εφαρμογή! Αν δεν το κάνουμε αυτό, κάποιοι το νήμα που θα μπορούσε να κάνει κάποια κρίσιμο μέρος θα ήταν νεκρός, και υπόλοιπο της αίτησης θα νομίζουν ότι όλα είναι φυσιολογικά. Από αυτό, πολλές ανεπιθύμητες καταστάσεις μπορεί να συμβεί. Ένα μικρότερο πρόβλημα είναι ότι δεν θα είναι σε θέση να βρείτε εύκολα ρίζα του προβλήματος, αν και άλλα θέματα ξεκινήσει ρίχνοντας μερικές εξαιρέσεις, λόγω της ένα νήμα που δεν εργάζονται.


Για παράδειγμα, συνήθως βρόχο θα πρέπει να είναι:



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

```

Ακόμη και σε ορισμένες περιπτώσεις, θα θέλατε να χειριστεί διαφορετικά τα λάθη με διαφορετικό τρόπο, για παράδειγμα, σε OutOfMemoryError θα είναι σε θέση να κλείσει την εφαρμογή τακτικά (ακόμα και ίσως ελευθερώσετε μνήμη, και να συνεχίσει), για κάποιους άλλους, δεν υπάρχουν πολλά που μπορείτε να κάνετε.

 

Πολύ σπάνια.


Θα πω μόνο στο ανώτερο επίπεδο του νήματος, ώστε να επιχειρήσει να εκδώσει ένα μήνυμα με το λόγο για μια ετοιμοθάνατη νήμα.


Αν είστε σε ένα πλαίσιο που κάνει αυτό το πράγμα για σας, αφήστε το στο πλαίσιο.

 

Αν είστε τρελοί αρκετά για να δημιουργήσει ένα νέο πλαίσιο δοκιμής μονάδα, τεστ δρομέας σας θα χρειαστεί κατά πάσα πιθανότητα να πιάσει java.lang.AssertionError ρίχνονται από τις περιπτώσεις δοκιμών.


Διαφορετικά, δείτε άλλες απαντήσεις.

 

**Μια `Error`συνήθως δεν πρέπει να πιαστεί** , όπως **δείχνει μια ανώμαλη κατάσταση που δεν πρέπει ποτέ να συμβεί** .


Από το API Προδιαγραφές Java για την [`Error`](http://java.sun.com/javase/6/docs/api/java/lang/Error.html)κατηγορία:



> 
> Ένα `Error`είναι μια υποκατηγορία `Throwable`
>  που υποδεικνύει σοβαρά προβλήματα που η λογική εφαρμογή δεν θα πρέπει να προσπαθήσει να πιάσει. Τα περισσότερα τέτοια λάθη είναι μη φυσιολογικές συνθήκες. [...]
> 
> 
> Μία μέθοδος δεν χρειάζεται να δηλώσουν τους ρίχνει ρήτρα οποιαδήποτε υποκατηγορίες των σφαλμάτων που μπορεί να ρίχνονται κατά την εκτέλεση της μεθόδου, αλλά δεν έπιασε, δεδομένου ότι αυτά τα λάθη είναι μη φυσιολογικές συνθήκες που δεν πρέπει ποτέ να συμβεί.
> 
> 
> 


Καθώς η προδιαγραφή αναφέρει, η `Error`ρίχνεται μόνο σε περιπτώσεις που είναι πιθανότητες είναι, όταν `Error`συμβαίνει, υπάρχει πολύ μικρή η εφαρμογή μπορεί να κάνει, και σε ορισμένες περιπτώσεις, η ίδια η Java Virtual Machine μπορεί να είναι σε μια ασταθή κατάσταση (όπως [`VirtualMachineError`](http://java.sun.com/javase/6/docs/api/java/lang/VirtualMachineError.html))


Αν και `Error`είναι μια υποκατηγορία των `Throwable`οποίων σημαίνει ότι μπορεί να πιαστεί από μια `try-catch`ρήτρα, αλλά κατά πάσα πιθανότητα δεν είναι πραγματικά αναγκαία, καθώς η εφαρμογή θα είναι σε μια μη φυσιολογική κατάσταση όταν `Error`ρίχνεται από το JVM.


Υπάρχει επίσης ένα μικρό τμήμα για το θέμα αυτό στο τμήμα [11.5 εξαίρεση Ιεραρχία](http://java.sun.com/docs/books/jls/second_edition/html/exceptions.doc.html#44278) της [Γλώσσας προδιαγραφή Java, 2η έκδοση](http://java.sun.com/docs/books/jls/second_edition/html/jTOC.doc.html) .

 

Σχεδόν ποτέ. Τα σφάλματα σχεδιαστεί για να είναι τα θέματα που τις εφαρμογές γενικά δεν μπορεί να κάνει τίποτα. Η μόνη εξαίρεση θα μπορούσε να είναι για να χειριστεί την παρουσίαση του σφάλματος, αλλά ακόμη και αυτό δεν θα μπορούσε να πάει όπως έχει προγραμματιστεί, ανάλογα με το σφάλμα.

 

Και υπάρχουν μερικές άλλες περιπτώσεις, αν σας πιάσει ένα σφάλμα, θα ***πρέπει να το rethrow*** . Για παράδειγμα [ThreadDeath](http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadDeath.html) δεν πρέπει ποτέ να πιαστεί, μπορεί να προκαλέσει μεγάλο πρόβλημα είναι να το πιάσει στη συγκράτηση περιβάλλον (π.χ. έναν διακομιστή εφαρμογών.):



> 
> Η αίτηση θα πρέπει να πιάσει περιπτώσεις αυτής της κατηγορίας μόνο αν πρέπει να καθαρίσει αφού τερματιστεί ασύγχρονα. Αν ThreadDeath πιάνεται με μια μέθοδο, είναι σημαντικό ότι θα rethrown έτσι ώστε το νήμα πεθαίνει πραγματικά.
> 
> 
> 

 

Πολύ, πολύ σπάνια.


Το έκανα μόνο για ένα πολύ πολύ συγκεκριμένες γνωστές περιπτώσεις. Για παράδειγμα, java.lang.UnsatisfiedLinkError θα μπορούσε να ρίξει εάν δύο **ανεξαρτησία ClassLoader** φορτίο ίδια DLL. (Συμφωνώ ότι θα πρέπει να μετακινήσετε το JAR σε έναν κοινόχρηστο ClassLoader)


Αλλά πιο συνηθισμένη περίπτωση είναι ότι χρειάζεται να συνδεθείτε για να ξέρετε τι συνέβη όταν ο χρήστης έρθει να παραπονεθεί. Θέλετε ένα μήνυμα ή ένα αναδυόμενο παράθυρο με το χρήστη, τότε μάλλον σιωπηλά νεκρούς.


Ακόμη και προγραμματιστής σε C / C ++, θα εμφανιστεί ένα σφάλμα και να πει κάτι που οι άνθρωποι δεν καταλαβαίνουν πριν από την έξοδο (π.χ. αποτυχία μνήμης).

 

Είναι πολύ βολικό να πιάσει java.lang.AssertionError σε ένα περιβάλλον δοκιμών ...

 

Σε μια εφαρμογή Android είμαι πιάσει ένα [java.lang.VerifyError](http://developer.android.com/reference/java/lang/VerifyError.html) . Μια βιβλιοθήκη που χρησιμοποιώ δεν θα λειτουργήσει σε συσκευές με μια παλιά έκδοση του λειτουργικού συστήματος και του κώδικα της βιβλιοθήκης θα ρίξει ένα τέτοιο σφάλμα. Θα μπορούσα βέβαια να αποφευχθεί το σφάλμα, ελέγχοντας την έκδοση του λειτουργικού συστήματος κατά το χρόνο εκτέλεσης, αλλά:


* Το παλαιότερο υποστήριξε SDK μπορεί να αλλάξει στο μέλλον για τη συγκεκριμένη βιβλιοθήκη
* Το μπλοκ σφάλμα δοκιμή αλιεύματα είναι μέρος ενός μεγαλύτερου πέφτουν μηχανισμό. Μερικές συγκεκριμένες συσκευές, αν και υποτίθεται ότι υποστηρίζουν τη βιβλιοθήκη, να ρίξει εξαιρέσεις. Πιάνω VerifyError και όλες τις εξαιρέσεις να χρησιμοποιήσετε μια λύση πίσω πτώση.

 

Στην ιδανική περίπτωση δεν θα πρέπει να χειριστεί / λάθη αλιευμάτων. Αλλά μπορεί να υπάρχουν περιπτώσεις όπου πρέπει να κάνουμε, με βάση την απαίτηση πλαίσιο ή την εφαρμογή. Ας υποθέσουμε ότι έχω ένα Parser δαίμονα XML που υλοποιεί **DOM Parser** που καταναλώνει περισσότερη μνήμη. Αν υπάρχει μια απαίτηση όπως το νήμα Parser δεν πρέπει να πεθάνει, όταν παίρνει **OutOfMemoryError** , αντ 'αυτού θα πρέπει να το χειριστεί και να στείλετε ένα μήνυμα / mail στο διαχειριστή της εφαρμογής / πλαισίου.

 

Υπάρχει ένα σφάλμα όταν το JVM δεν είναι τίποτα περισσότερο λειτουργεί όπως θα έπρεπε, ή είναι στα πρόθυρα να. Αν σας πιάσει ένα λάθος, δεν υπάρχει καμία εγγύηση ότι το μπλοκ των αλιευμάτων θα τρέξει, και ακόμη λιγότερο ότι θα τρέξει μέχρι το τέλος.


Θα εξαρτηθεί επίσης από τον υπολογιστή σε λειτουργία, η τρέχουσα κατάσταση της μνήμης, έτσι δεν υπάρχει κανένας τρόπος για να δοκιμάσει, να προσπαθήσουμε και να κάνουμε το καλύτερο σας. Θα έχετε μόνο μια hasardous αποτέλεσμα.


Θα υποβαθμίσει και την αναγνωσιμότητα του κώδικα σας.

 

Θα μπορούσε να είναι σκόπιμο να πιάσει το σφάλμα στη μονάδα δοκιμές που ελέγχουν ένας ισχυρισμός που γίνεται. Αν κάποιος απενεργοποιεί ισχυρισμούς ή άλλως διαγράφει ο ισχυρισμός θα θέλατε να ξέρετε

 

στην ιδανική περίπτωση θα πρέπει ποτέ να πιάσει σφάλματος στην εφαρμογή μας Java, δεδομένου ότι είναι μια ανώμαλη κατάσταση. Η εφαρμογή θα είναι σε φυσιολογική κατάσταση και μπορεί να οδηγήσει σε carshing ή δίνοντας κάποιο σοβαρό λάθος αποτέλεσμα.

 