W jakich sytuacjach należy złapać java.lang.Error
na aplikacji?
Kiedy złapać java.lang.Error?
Prawie nigdy. Błędy są przeznaczone do kwestii, że aplikacje na ogół nie można robić nic na temat. Jedynym wyjątkiem może być obsługiwać prezentację błędu, ale nawet to może nie pójść zgodnie z planem, w zależności od błędu.
Nigdy. Nigdy nie można być pewnym, że aplikacja jest w stanie wykonać następną linię kodu. Jeśli masz OutOfMemoryError
, masz żadnej gwarancji, że będzie można zrobić wszystko niezawodnie . Złap RuntimeException i sprawdzone wyjątkami, ale nigdy błędów.
I istnieje kilka innych przypadkach, jeśli złapiesz błąd, to trzeba go rethrow . Na przykład ThreadDeath nigdy nie powinien być złapany, może to spowodować duży problem jest złapać go w zamkniętym środowisku (np serwera aplikacji.):
Wniosek powinien złapać instancje tej klasy tylko wtedy, gdy musi posprzątać po rozwiązana jest asynchronicznie. Jeśli ThreadDeath zostaje złapany przez sposób, ważne jest, aby być rethrown tak, że wątek rzeczywiście umiera.

Ogólnie rzecz biorąc, nigdy. Jednak czasami trzeba złapać konkretne błędy.
Jeśli piszesz kod framework-owski (ładowanie klas 3rd party), to może być mądry, aby złapać LinkageErrors (bez klasy def znaleziony, niezadowolony odnośnik niezgodne zmiany klasa). Ja również widziałem jakieś głupie kod 3rd partii rzucanie sublcasses błędów, więc będziesz musiał obsługiwać te albo.
Nawiasem mówiąc, nie jestem pewien, że nie jest możliwy do odzyskania od OutOfMemory.
Bardzo rzadko.
Powiedziałbym tylko na najwyższym poziomie wątku, aby próbować wydać komunikat z powodów dla umierających gwintu.
Jeśli jesteś w ramy, które robi tego rodzaju rzeczy dla ciebie, zostaw go do ramy.
Error
Zazwyczaj nie powinien być złapany , gdyż wskazuje na nieprawidłowy stan, który nigdy nie powinien wystąpić .
Ze specyfikacją Java API dla Error
klasy:
Error
Jest podklasąThrowable
, która wskazuje, że poważne problemy rozsądny wniosek nie powinien spróbować złapać. Większość tego rodzaju błędy są anormalne warunki. [...]Metoda nie jest wymagane, aby zadeklarować w jego rzutów klauzula żadnych podklasy błędu, który może być rzucony podczas wykonywania metody, ale nie złapany, ponieważ te błędy są anormalne warunki, które nigdy nie powinny występować.
Ponieważ specyfikacja wspomina, Error
jest wyrzucany tylko w okolicznościach, które są Szanse są, kiedy Error
występuje, jest bardzo mało, aplikacja może zrobić, w niektórych okolicznościach, Java Virtual sama maszyna może być w stanie niestabilnym (jak VirtualMachineError
)
Chociaż Error
jest podklasą Throwable
co oznacza, że może zostać złapany przez try-catch
klauzuli, ale to chyba nie jest naprawdę potrzebne, a aplikacja będzie w nienormalnym stanie, gdy Error
jest wyrzucany przez JVM.
Jest też krótki odcinek na ten temat w rozdziale 11.5 hierarchii Wyjątek od języka Java Specification, 2nd Edition .
Bardzo, bardzo rzadko.
Zrobiłem to tylko dla jednego bardzo konkretnych znanych przypadków. Na przykład, można by rzucać java.lang.UnsatisfiedLinkError jeśli dwa niezależność ClassLoader obciążenia samego DLL. (Zgadzam się, że należy przesunąć JAR do udostępnionego classloader)
Ale najczęściej jest tak, że trzeba było zalogowaniu, aby wiedzieć, co się stało, gdy użytkownik przyjść narzekać. Chcesz wiadomość lub okienko do użytkownika, a następnie cicho martwy.
Nawet programista w C / C ++, ponieważ pop błąd i powiedzieć coś ludzie nie rozumieją, że przed wyjściem (np awaria pamięci).
Jeśli jesteś na tyle szalony, aby być stworzenie nowych ram testów jednostkowych, Twój testy biegacz będzie prawdopodobnie trzeba złapać java.lang.AssertionError rzucony przez wszelkich przypadków testowych.
W przeciwnym razie zobacz inne odpowiedzi.
Generalnie należy zawsze złapać java.lang.Error
i pisać to do dziennika lub wyświetlić go do użytkownika. Pracuję na poparcie i zobaczyć codziennie, że programiści nie może powiedzieć, co działo się w programie.
Jeśli masz wątek demona musisz uniknąć ryzyka zakończone. W innych przypadkach aplikacja będzie działać prawidłowo.
Należy złapać tylko java.lang.Error
na najwyższym poziomie.
Jeśli spojrzeć na listę błędów można zauważyć, że większość z nich może być obsługiwane. Na przykład ZipError
występuje na czytanie uszkodzone pliki zip.
Najczęstsze błędy OutOfMemoryError
i NoClassDefFoundError
, które są zarówno w większości przypadków problemów wykonawczych.
Na przykład:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
mogą wytwarzać OutOfMemoryError
, ale jest to problem, wykonawcze i nie ma powodu, aby zakończyć program.
NoClassDefFoundError
występują głównie jeśli biblioteka nie jest obecny lub jeśli pracujesz z innej wersji Java. Jeśli jest to opcjonalna część programu to nie powinien zakończyć swój program.
Mogę podać wiele więcej przykładów, dlaczego jest to dobry pomysł, aby złapać Throwable
na najwyższym poziomie i produkować pomocne komunikat o błędzie.
W środowisku wielowątkowym, to najczęściej chcą go złapać! Gdy go złapać, zalogować się i zakończyć całą aplikację! Jeśli tego nie robią, niektóre nici, które mogą być jakiejś kluczową rolę będzie martwy, a reszta aplikacji będą myśleć, że wszystko jest normalne. Poza tym, wiele niechciane sytuacje mogą się zdarzyć. Jeden najmniejszym problemem jest to, że nie będzie w stanie łatwo znaleźć źródło problemu, jeśli inne wątki zacząć rzucać wyjątki ze względu na jeden wątek nie działa.
Dla przykładu, zwykle pętli powinna być:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
Nawet w niektórych przypadkach, co chcesz obsługiwać różne błędy w różny sposób, na przykład, na OutOfMemoryError byłbyś w stanie regularnie zamknąć aplikację (nawet może uwolnić trochę pamięci i dalej), na niektórych innych, nie ma wiele można zrobić.
idealnie nigdy nie powinniśmy złapać błąd w naszej aplikacji Java, ponieważ jest to nienormalny stan. Aplikacja będzie w nienormalnym stanie i może spowodować carshing lub dając trochę poważnie zły wynik.
To może być odpowiednie do połowu błędów w testach jednostkowych, które sprawdzają twierdzenie jest wykonany. Jeśli ktoś wyłącza twierdzeń lub w inny sposób usuwa twierdzenie co chcesz wiedzieć
W aplikacji Android mam złapanie java.lang.VerifyError . Biblioteka że używam nie będzie działać w urządzeniach ze starą wersją systemu operacyjnego i kodzie biblioteki rzuci takiego błędu. Mógłbym oczywiście uniknąć błędu, sprawdzając wersję systemu operacyjnego przy starcie, ale:
- Najstarsza obsługiwane SDK może się zmienić w przyszłości dla określonej biblioteki
- Blok try-catch błąd jest częścią większego sięgnięcie mechanizmu. Niektóre konkretne urządzenia, chociaż oni mają obsługiwać bibliotekę, rzucać wyjątki. Złapię VerifyError i wszystkie wyjątki użyć cofać rozwiązanie.
Wystąpił błąd podczas JVM więcej nie działa zgodnie z oczekiwaniami, lub jest na granicy do. Jeśli złapiesz błąd, nie ma gwarancji, że blok catch będzie działać, a nawet mniej, że to będzie działać do końca.
Będzie ona również zależeć na komputerze uruchomiony, aktualnego stanu pamięci, więc nie ma możliwości, aby przetestować, wypróbować i jak najlepiej. Trzeba będzie jedynie hasardous wynik.
Będziesz także obniżyć czytelność kodu.
to jest bardzo przydatny do połowu java.lang.AssertionError w środowisku testowym ...
Idealnie nie powinny obsługiwać / błędy połowów. Ale nie mogą być przypadki, w których musimy zrobić, na podstawie wymogu ram lub aplikacji. Że mam demona parsera XML, który implementuje parser DOM , który zużywa więcej pamięci. Jeśli istnieje wymóg jak Parser wątku nie należy zmarł, gdy robi OutOfMemoryError zamiast powinien go obsłużyć i wysłać wiadomość / mail do administratora aplikacji / ramy.