Czy można zbudować fragment kodu w Javie , który uczyniłby hipotetyczną nie do zdobycia java.lang.ChuckNorrisException
?
Przemyślone myśli wykorzystują na przykład przechwytywacze lub programowanie zorientowane na aspekty .
java
exception
exception-handling
aop
Max Charas
źródło
źródło
finalize()
?Odpowiedzi:
Nie próbowałem tego, więc nie wiem, czy JVM ograniczyłby coś takiego, ale być może mógłbyś skompilować kod, który rzuca
ChuckNorrisException
, ale w czasie wykonywania podaj definicję klasy,ChuckNorrisException
która nie rozszerza Throwable .AKTUALIZACJA:
To nie działa Generuje błąd weryfikatora:
AKTUALIZACJA 2:
Właściwie możesz to uruchomić, jeśli wyłączysz weryfikator kodu bajtowego! (
-Xverify:none
)AKTUALIZACJA 3:
Dla tych, którzy przychodzą z domu, oto pełny skrypt:
Utwórz następujące klasy:
Klasy kompilacji:
Biegać:
Skomentuj „przedłuża wyjątek RuntimeException” i rekompiluj
ChuckNorrisException.java
tylko :Biegać:
Uruchom bez weryfikacji:
źródło
Object
zamiastThrowable
, to? (Kompilator na to nie zezwala, ale skoro już wyłączyliśmy weryfikator, być może można by zhakować kod bajtowy, aby to zrobić.)Po zastanowieniu się, udało mi się stworzyć wyjątkowy wyjątek. Zdecydowałem się jednak nazwać to
JulesWinnfield
, a nie Chuck, ponieważ jest to jeden wyjątek od grzybów-chmur-matek-matek. Co więcej, może nie być to dokładnie to, co miałeś na myśli, ale na pewno nie da się go złapać. Przestrzegać:Zrobione! Nieprzechwycony wyjątek.
Wynik:
Kiedy będę miał trochę więcej czasu, zobaczę, czy nie mogę wymyślić czegoś innego.
Sprawdź również:
Powoduje przepełnienie stosu - ponownie wyjątki pozostają nieprzechwycone.
źródło
JulesWinfield
? Czy system nie zatrzyma się z piskiem, zanim zostanie wyrzucony?throw new Whatever()
to tak naprawdę dwie części:Whatever it = new Whatever(); throw it;
i system umiera, zanim dotrze do drugiej części.class cn extends exception{private cn(){}}
Z takim wyjątkiem byłoby oczywiście obowiązkowe użycie
System.exit(Integer.MIN_VALUE);
konstruktora, ponieważ tak by się stało, gdybyś rzucił taki wyjątek;)źródło
while(true){}
zamiastSystem.exit()
.System.exit()
pracę, instalując menedżera bezpieczeństwa, który go zabrania. zmieniłoby to konstruktor w inny wyjątek (SecurityException), który mógł zostać przechwycony.Każdy kod może złapać Throwable. Więc nie, jakikolwiek wyjątek, który stworzysz, będzie podklasą Throwable i będzie podlegał złapaniu.
źródło
hang
sam spróbowałby złapać(To prawda, że technicznie ten wyjątek nigdy nie jest generowany, ale
ChuckNorrisException
nie można go wyrzucić - rzuca cię pierwszy).źródło
Każdy rzucony wyjątek musi przedłużać Throwable, aby zawsze można go było złapać. Więc odpowiedź brzmi nie.
Jeśli chcesz, aby to trudne w obsłudze, można przesłonić metody
getCause(), getMessage()
,getStackTrace()
,toString()
aby rzucić innyjava.lang.ChuckNorrisException
.źródło
catch(Throwable t)
przechowuje go tylko w zmiennej, więc moje sugestie mają zastosowanie tylko w następnym bloku, gdy użytkownik chce poradzić sobie z wyjątkiemMoja odpowiedź opiera się na pomyśle @ jtahlborn, ale jest to w pełni działający program Java , który można spakować do pliku JAR , a nawet wdrożyć na ulubionym serwerze aplikacji jako część aplikacji internetowej .
Po pierwsze, zdefiniujmy
ChuckNorrisException
klasę, aby nie powodowała awarii JVM od samego początku (Chuck naprawdę uwielbia zawieszanie JVM BTW :)Teraz idzie
Expendables
klasa, aby go zbudować:I w końcu
Main
klasa skopała tyłek:Skompiluj i uruchom go za pomocą następującego polecenia:
Otrzymasz następujące dane wyjściowe:
Nic dziwnego - w końcu to kopnięcie wkoło :)
źródło
W konstruktorze możesz uruchomić wątek, który wielokrotnie wywołuje
originalThread.stop (ChuckNorisException.this)
Wątek mógł wielokrotnie wychwytywać wyjątek, ale rzucałby go aż do śmierci.
źródło
Nie. Wszystkie wyjątki w Javie muszą być podklasowane
java.lang.Throwable
i chociaż może to nie być dobrą praktyką, możesz wychwycić każdy typ wyjątku:Zobacz uzyskać więcej informacji, dokumentację java.lang.Throwable .
Jeśli próbujesz uniknąć zaznaczonych wyjątków ( wyjątków , które muszą być jawnie obsługiwane), możesz podklasę Błąd lub RuntimeException.
źródło
W rzeczywistości zaakceptowana odpowiedź nie jest tak ładna, ponieważ Java musi być uruchomiona bez weryfikacji, tzn. Kod nie działałby w normalnych okolicznościach.
AspectJ na ratunek dla prawdziwego rozwiązania !
Klasa wyjątków:
Aspekt:
Przykładowa aplikacja:
Wynik:
źródło
Wariantem tego motywu jest zaskakujący fakt, że można rzucać niezadeklarowane sprawdzone wyjątki od kodu Java. Ponieważ nie jest zadeklarowany w podpisie metod, kompilator nie pozwala na przechwycenie samego wyjątku, chociaż można go przechwycić jako java.lang.Exception.
Oto klasa pomocnicza, która pozwala rzucać wszystko, zadeklarowane lub nie:
Teraz
throw SneakyThrow.sneak(new ChuckNorrisException());
generuje wyjątek ChuckNorrisException, ale kompilator narzekao przechwytywaniu wyjątku, który nie jest zgłaszany, jeśli wyjątek ChuckNorrisException jest sprawdzonym wyjątkiem.
źródło
Jedynymi
ChuckNorrisException
literami w Javie powinny byćOutOfMemoryError
iStackOverflowError
.Możesz faktycznie „złapać” je w sposób, który oznacza
catch(OutOfMemoryError ex)
wykona się w przypadku zgłoszenia wyjątku, ale blok ten automatycznie zwróci wyjątek dzwoniącemu.Nie sądzę, że to wystarcza,
public class ChuckNorrisError extends Error
ale możesz spróbować. Nie znalazłem dokumentacji dotyczącej rozszerzeniaError
źródło
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
Tak, a oto odpowiedź: Zaprojektuj
java.lang.ChuckNorrisException
taki, aby nie był to przypadekjava.lang.Throwable
. Dlaczego? Obiekt niemożliwy do zdefiniowania jest z definicji nie do złapania, ponieważ nigdy nie można złapać czegoś, czego nigdy nie można wyrzucić.źródło
java.lang.ChuckNorrisException
muszą być wyjątkiem, nie mówiąc już o rzucaniuMożesz zachować ChuckaNorrisa wewnętrznie lub prywatnie i obudować go lub pochłonąć ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
źródło
Dwa podstawowe problemy z obsługą wyjątków w Javie polegają na tym, że używa on typu wyjątku, aby wskazać, czy należy na nim podjąć działanie, i że zakłada się, że wszystko, co podejmuje działanie w oparciu o wyjątek (tj. „Przechwytuje” to) warunek podstawowy. Przydatne byłoby posiadanie środków, dzięki którym obiekt wyjątku mógłby decydować, które procedury obsługi powinny zostać wykonane i czy procedury obsługi, które do tej pory wykonały, wyczyściły wszystko wystarczająco, aby obecny sposób mógł spełnić warunki wyjścia. Chociaż można tego użyć do stworzenia „niemożliwych do uchwycenia” wyjątków, dwa większe zastosowania to (1) wprowadzenie wyjątków, które będą rozpatrywane tylko wtedy, gdy zostaną przechwycone przez kod, który faktycznie wie, jak sobie z nimi poradzić, i (2) zezwolą do rozsądnego obchodzenia się z wyjątkami, które występują w
finally
FooException
podczasfinally
bloku podczas odwijania aBarException
oba wyjątki powinny propagować stos wywołań; oba powinny być możliwe do złapania, ale rozwijanie powinno trwać, dopóki nie zostaną złapane). Niestety nie sądzę, aby istniał jakiś sposób, aby istniejący kod obsługi wyjątków działał w ten sposób bez zepsucia rzeczy.źródło
finally
czyszczenia bloku z wcześniejszego wyjątku, jest całkiem możliwe, że którykolwiek wyjątek, przy braku drugiego, może być czymś, co kod mógłby obsłużyć i kontynuować, ale radzenie sobie z jednym i ignorowanie drugiego byłoby złe. Nie ma jednak mechanizmu generowania złożonego wyjątku, który przetworzyłyby oba programy obsługi.Foo
może odróżnić wyjątek, któryFoo
albo sam się rzucił, albo celowo chce udawać, że sam się rzucił, od tego, któryFoo
nie spodziewał się, że nastąpi wywołanie innej metody. Właśnie tym pojęciem „sprawdzonych” wyjątków powinno być „około”.Łatwo jest zasymulować niewyłapany wyjątek dla bieżącego wątku. Spowoduje to normalne zachowanie nieprzechwyconego wyjątku, a tym samym wykonanie zadania semantycznie. Niekoniecznie jednak zatrzyma to wykonywanie bieżącego wątku, ponieważ tak naprawdę nie zostanie zgłoszony żaden wyjątek.
Jest to faktycznie przydatne w (bardzo rzadkich) sytuacjach, na przykład gdy
Error
wymagana jest poprawna obsługa, ale metoda jest wywoływana z frameworka, który przechwytuje (i odrzuca) dowolneThrowable
.źródło
Wywołaj System.exit (1) w
finalize
i po prostu wyrzuć kopię wyjątku ze wszystkich innych metod, aby program się zakończył.źródło