Czytałem książkę o umiejętnościach programistycznych, w której autor pyta rozmówcę: „Jak załamać JVM?” Pomyślałem, że możesz to zrobić, pisząc nieskończoną pętlę for, która ostatecznie zużyje całą pamięć.
stackoverflow.com/questions/30072883/… "Jeśli używam JDK1.8_40 lub nowszego (Oracle lub OpenJDK robią to samo), poniższy kod wraz z okienkiem zmiany rozmiaru spowoduje awarię aplikacji (wypróbowany Windows 7, x64, 64-bitowy JDK)" - Kod ma tylko 40 linii i powoduje poprawną awarię maszyny JVM.
Prezes Dreamspace
Odpowiedzi:
6
Najbliższą pojedynczą „odpowiedzią” jest System.exit()natychmiastowe zamknięcie maszyny JVM bez odpowiedniego czyszczenia. Ale poza tym najbardziej prawdopodobnymi odpowiedziami są kod natywny i wyczerpanie zasobów. Alternatywnie możesz poszukać w module śledzenia błędów firmy Sun błędów w Twojej wersji maszyny JVM, z których niektóre pozwalają na powtarzalne scenariusze awarii. Kiedyś otrzymywaliśmy pół-regularne awarie, gdy zbliżaliśmy się do limitu pamięci 4 Gb w wersjach 32-bitowych (zwykle używamy teraz 64-bitów).
bez odpowiedniego czyszczenia? Jesteś pewny? Dokumentacja mówi: „Kończy aktualnie uruchomioną wirtualną maszynę Java poprzez zainicjowanie jej sekwencji zamykania… wszystkie zarejestrowane punkty zaczepienia zamykania systemu, jeśli takie istnieją, są uruchamiane… wszystkie nie wywołane finalizatory są uruchomione” - czy to nie jest właściwe czyszczenie?
user85421
51
To nie jest awaria maszyny JVM, jest to celowe i jawne rozpoczęcie uporządkowanego zamykania wykonywania.
BenM
9
Bliżej awarii jvm jest Runtime.getRuntime (). Halt (status). Zgodnie z dokumentacją „ta metoda nie powoduje uruchamiania przechwytywania zamykania systemu i nie uruchamia nie wywołanych finalizatorów, jeśli włączono finalizację przy wyjściu”. Nadal nie jest to awaria, ale bliżej niż System.exit.
henry
48
To naprawdę zła odpowiedź.
Antonio
174
Nie nazwałbym wyrzucania OutOfMemoryError lub StackOverflowError awarią. To są zwykłe wyjątki. Aby naprawdę zawiesić maszynę wirtualną, istnieją 3 sposoby:
Użyj JNI i ulegnij awarii w kodzie natywnym.
Jeśli nie jest zainstalowany żaden menedżer zabezpieczeń, możesz użyć odbicia, aby zawiesić maszynę wirtualną. Jest to specyficzne dla maszyny wirtualnej, ale zwykle maszyna wirtualna przechowuje zestaw wskaźników do zasobów natywnych w polach prywatnych (np. Wskaźnik do obiektu natywnego wątku jest przechowywany w długim polu w java.lang.Thread ). Po prostu zmień je za pomocą odbicia, a maszyna wirtualna prędzej czy później ulegnie awarii.
Wszystkie maszyny wirtualne mają błędy, więc wystarczy je uruchomić.
W przypadku ostatniej metody mam krótki przykład, który spowoduje ładną awarię maszyny wirtualnej Sun Hotspot:
publicclassCrash{publicstaticvoid main(String[] args){Object[] o =null;while(true){
o =newObject[]{o};}}}
Prowadzi to do przepełnienia stosu w GC, więc nie otrzymasz StackOverflowError, ale prawdziwy błąd, w tym plik hs_err *.
Łał! Powoduje to awarię Sun Java 5, Sun Java 6 i OpenJDK 6 (w Ubuntu 9.04) bez pliku hs_err *, ale tylko z komunikatem „Błąd segmentacji!” ...
Joachim Sauer
1
System.exit () to znacznie łatwiejszy sposób na awarię maszyny JVM (chyba że zainstalowano menedżera bezpieczeństwa)
instantsetsuna
4
Nie wiem, kiedy zostało to naprawione, ale właśnie przetestowałem w wersji 1.7.0_09 i wszystko jest w porządku. Właśnie otrzymałem oczekiwane: Wyjątek w wątku „main” java.lang.OutOfMemoryError: Miejsce na sterty Java w CrashJVM.main (CrashJVM.java:7)
Czad NB
2
Wypróbowałem powyższy kod na Intel Core i7 2,4 GHz / 8 GB RAM / JDK1.7 64bit, ale JVM nadal działa po 20 minutach. (Zabawne: mój wentylator laptopa był głośniejszy niż myśliwiec na niebie). Czy ten problem został rozwiązany w JDK 1.7+?
realPK
3
W JDK 1.8_u71 powoduje tojava.lang.OutOfMemoryError: GC overhead limit exceeded
Clashsoft
124
JNI . W rzeczywistości w przypadku JNI zawieszanie się jest domyślnym trybem działania. Musisz bardzo ciężko pracować, aby się nie zawiesił.
Zamiast używać -Xbootclasspath, możesz po prostu zrobić to: Field f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );dla mnie zadziałało świetnie.
nachalny
Unsafejest z definicji „niebezpieczny”. To trochę oszustwo.
Hot Licks
1
Potwierdzono pracę przy użyciu getDeclaredFieldsztuczki w JDK 8u131 na Linux x64, w tym produkcję hs_err_pid*.logz pliku SIGSEGV.
Jesse Glick
Używanie Unsafenie jest oszustwem. OP nie szuka „czystego” rozwiązania problemu programistycznego. Potrzebuje jvm do awarii w najbrzydszy możliwy sposób. Robienie paskudnych, rodzimych rzeczy jest tym, co może do tego doprowadzić, i właśnie tak Unsafejest.
jvdneste,
34
Przyszedłem tutaj, ponieważ natknąłem się na to pytanie w The Passionate Programmer autorstwa Chada Fowlera. Dla tych, którzy nie mają dostępu do kopii, pytanie to jest traktowane jako rodzaj filtru / testu dla kandydatów przeprowadzających rozmowy kwalifikacyjne na stanowisko wymagające „naprawdę dobrych programistów Java”.
W szczególności pyta:
Jak napisałeś program w czystej Javie, który powodowałby awarię wirtualnej maszyny Java?
Programuję w Javie od ponad 15 lat i uznałem to pytanie za zagadkowe i niesprawiedliwe. Jak zauważyli inni, Java, jako język zarządzany, została specjalnie zaprojektowana, aby nie ulegać awariom . Oczywiście zawsze są błędy JVM, ale:
Po ponad 15 latach JRE na poziomie produkcyjnym jest to rzadkie.
Jakiekolwiek takie błędy prawdopodobnie zostaną załatane w następnym wydaniu, więc jak prawdopodobne jest, że jako programista natkniesz się na i przypomnisz sobie szczegóły obecnego zestawu blokad pokazów JRE?
Jak wspominali inni, część kodu natywnego za pośrednictwem JNI to pewny sposób na awarię środowiska JRE. Ale autor wyraźnie wspomniał w czystej Javie , więc to się skończyło.
Inną opcją byłoby podanie fałszywych kodów bajtowych środowiska JRE; dość łatwo jest zrzucić trochę śmieciowych danych binarnych do pliku .class i poprosić środowisko JRE o jego uruchomienie:
$ echo 'crap crap crap'> crap.class
$ java crap
Exception in thread "main" java.lang.ClassFormatError:Incompatible magic value 1668440432 in class file crap
To się liczy? Mam na myśli to, że samo środowisko JRE nie uległo awarii; poprawnie wykrył fałszywy kod, zgłosił go i zakończył pracę.
To pozostawia nam najbardziej oczywiste rodzaje rozwiązań, takie jak przepuszczanie stosu przez rekurencję, wyczerpywanie się pamięci sterty przez alokacje obiektów lub po prostu rzucanie RuntimeException. Ale to po prostu powoduje zamknięcie środowiska JRE z StackOverflowErrorlub podobnym wyjątkiem, co ponownie nie jest tak naprawdę awarią .
Więc co zostało? Bardzo chciałbym usłyszeć, co autor miał na myśli jako właściwe rozwiązanie.
Takie pytania z wywiadu służą jako papierki lakmusowe dla programistów Java, którzy istnieją wystarczająco długo, aby 1) byli świadkami (wielu) awarii JVM i 2) wyciągnęli jakieś wnioski lub, jeszcze lepiej, ponieważ (samozwańczy) eksperci Java próbowali zrozumieć podstawowe przyczyny awarii. Chad Fowler stwierdza również w swojej książce, że samozwańczy programiści Javy „nie mogli nawet znaleźć złej odpowiedzi”, tj. Nie próbowali myśleć o całej klasie potencjalnych problemów. Podsumowując: to pytanie brzmi „Jak zapobiegać awariom JVM?” co najwyraźniej jeszcze lepiej wiedzieć.
Shonzilla
1
Szukałbym osób, które po prostu odpowiedziały (jak większość tutaj) „przepełnienie stosu”, system.exit () lub inne „normalne” zamknięcie, ponieważ tak naprawdę nie rozumieją JVM lub słowa „Crash”. Rozpoznanie (tak jak ty), że jest to bardzo nieprawidłowe, jest całkiem dobrym sposobem na zidentyfikowanie bardziej zaawansowanego programisty. Zgadzam się z twoim pierwszym stwierdzeniem, uważam, że jest to doskonałe i całkowicie uczciwe pytanie, które można zadać lub zostać zadane - te bez konkretnych odpowiedzi są zawsze najlepsze.
Bill K
20
Ten kod spowoduje awarię maszyny JVM w nieprzyjemny sposób
Błąd kompilacji podczas używania JDK 1.7 z tym kodem: Ograniczenie dostępu: Typ PathDasher nie jest dostępny z powodu ograniczenia wymaganej biblioteki C: \ Program Files \ Java \ jdk1.7.0_51 \ jre \ lib \ rt.jar
realPK
7
To rzuca InternalErrorJDK 1.8. JVM już nie zawodzi.
Sotirios Delimanolis
18
Ostatni raz, gdy próbowałem, zrobił to:
publicclassRecur{publicstaticvoid main(String[] argv){try{
recur();}catch(Error e){System.out.println(e.toString());}System.out.println("Ended normally");}staticvoid recur(){Object[] o =null;try{while(true){Object[] newO =newObject[1];
newO[0]= o;
o = newO;}}finally{
recur();}}}
Pierwsza część wygenerowanego pliku dziennika:
##An unexpected error has been detected by JavaRuntimeEnvironment:## EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6752, tid=1996##Java VM:JavaHotSpot(TM)64-BitServer VM (11.2-b01 mixed mode windows-amd64)#Problematic frame:# V [jvm.dll+0x2e5c3d]##If you would like to submit a bug report, please visit:# http://java.sun.com/webapps/bugreport/crash.jsp#--------------- T H R E A D ---------------Current thread (0x00000000014c6000):VMThread[stack:0x0000000049810000,0x0000000049910000][id=1996]
siginfo:ExceptionCode=0xc00000fd,ExceptionInformation=0x00000000000000010x0000000049813fe8Registers:
EAX=0x000000006dc83090, EBX=0x000000003680f400, ECX=0x0000000005d40ce8, EDX=0x000000003680f400
ESP=0x0000000049813ff0, EBP=0x00000000013f2df0, ESI=0x00000000013f0e40, EDI=0x000000003680f400
EIP=0x000000006dad5c3d, EFLAGS=0x0000000000010206
Jestem trochę rozbawiony negatywnym głosem, biorąc pod uwagę, że jest to jedna z niewielu odpowiedzi pokazujących, jak to zrobić wyłącznie za pomocą kodu Java, i zawiera cały kod.
Hot Licks
Zgadzam się, że głos przeciw nie jest uzasadniony - to prawdziwa katastrofa, ale jak byś odpowiedział na pytanie z wywiadu. O ile wcześniej tego nie zbadałeś i nie zapamiętałeś, nie możesz dać tego jako odpowiedzi w wywiadzie, a gdybyś mógł, i tak rozważyłbym odpowiedź neutralną lub złą - nie pokazuje, jak podejdziesz do problemu. Spodziewam się, że wyszukałeś w Google exploity błędów jvm i zaimplementowałeś jeden, co jest doskonałą odpowiedzią.
Bill K
@BillK - Nie, powyższe jest całkowicie moją własną pracą, chociaż wymyśliłem ją kilka lat temu, eksperymentując z różnymi rzeczami. W wywiadzie prawdopodobnie powiedziałbym: „Zrobiłem to, używając try / catch i rekurencji, ale nie mogę teraz znaleźć dokładnego kodu”.
Hot Licks
1
Jakie są szczegóły (wersja JDK, jakiekolwiek argumenty maszyny wirtualnej)? Nie wiem, jaka jest wersja „11.2-b0”. Używam tego, ale zużywa tylko dużo procesora.
Stefan Reich
@Hot Licks: Jaka jest koncepcja na przykładzie awarii maszyny JVM? Dlaczego JVM rozbija się o kod. Wszystkie wątki mają oddzielne wątki stosu ...
VJS
15
Idealna implementacja JVM nigdy nie ulegnie awarii.
Aby zawiesić maszynę JVM, oprócz JNI, musisz znaleźć błąd w samej maszynie wirtualnej. Nieskończona pętla po prostu zużywa procesor. Nieskończone przydzielanie pamięci powinno po prostu powodować błędy OutOfMemoryError w dobrze zbudowanej JVM. Prawdopodobnie spowodowałoby to problemy dla innych wątków, ale dobra JVM nadal nie powinna ulec awarii.
Jeśli możesz znaleźć błąd w kodzie źródłowym maszyny wirtualnej i na przykład spowodować błąd segmentacji w wykorzystaniu pamięci przez implementację maszyny wirtualnej, możesz ją faktycznie zawiesić.
Możesz wykonać nieskończoną rekurencję, aby zabrakło miejsca na stosie, ale to się zawiesi "wdzięcznie". Dostaniesz wyjątek, ale sama maszyna JVM będzie obsługiwać wszystko.
Możesz również użyć JNI do wywołania kodu natywnego. Jeśli nie zrobisz tego dobrze, możesz sprawić, że się zawiesi. Debugowanie tych awarii jest „zabawne” (zaufaj mi, musiałem napisać dużą bibliotekę DLL C ++, którą wywołujemy z podpisanego apletu java). :)
Książka Java Virtual Machine autorstwa Jona Meyera zawiera przykład serii instrukcji kodu bajtowego, które spowodowały zrzut pamięci JVM. Nie mogę znaleźć mojej kopii tej książki. Jeśli ktoś tam ma, poszukaj go i opublikuj odpowiedź.
Zepsuty sprzęt może spowodować awarię dowolnego programu. Kiedyś miałem powtarzalną awarię aplikacji na konkretnym komputerze, podczas gdy działała dobrze na innych komputerach z dokładnie taką samą konfiguracją. Okazuje się, że maszyna miała wadliwą pamięć RAM.
Nie rozbija się. Daje błąd czasu kompilacji Exception in thread "main" java.lang.StackOverflowError at Test.main. Używam jdk1.8.0_65
Quazi Irfan,
5
Nie awaria, ale bliżej awarii niż akceptowana odpowiedź użycia System.exit
Możesz zatrzymać JVM, dzwoniąc
Runtime.getRuntime().halt( status )
Według dokumentów: -
„ta metoda nie powoduje uruchomienia przechwytywania zamykania systemu i nie uruchamia nie wywołanych finalizatorów, jeśli włączono finalizację przy wyjściu”.
Znam kilka sposobów spowodowania zrzucenia przez maszynę JVM pliku błędu przez wywołanie metod natywnych (takich, które są wbudowane), ale prawdopodobnie najlepiej nie wiesz, jak to zrobić. ;)
Jeśli zdefiniujesz awarię jako przerwanie procesu z powodu nieobsługiwanej sytuacji (tj. Braku wyjątku Java lub błędu), nie można tego zrobić z poziomu Javy (chyba że masz uprawnienia do używania klasy sun.misc.Unsafe). To cały punkt zarządzanego kodu.
Typowe awarie w kodzie natywnym zdarzają się przez usuwanie odniesień do niewłaściwych obszarów pamięci (adres zerowy lub niewłaściwie wyrównany). Innym źródłem mogą być nielegalne instrukcje maszynowe (kody operacyjne) lub nieobsłużone sygnały z wywołań biblioteki lub jądra. Oba mogą zostać wyzwolone, jeśli JVM lub biblioteki systemowe zawierają błędy.
Na przykład kod JITed (wygenerowany), metody natywne lub wywołania systemowe (sterownik grafiki) mogą mieć problemy prowadzące do rzeczywistych awarii (dość często dochodziło do awarii, gdy korzystałeś z funkcji ZIP i zabrakło im pamięci). W takich przypadkach program obsługi awarii maszyny JVM włącza się i zrzuca stan. Może również wygenerować plik rdzenia systemu operacyjnego (Dr. Watson w systemie Windows i zrzut rdzenia na * nix).
W systemie Linux / Unix możesz łatwo spowodować awarię JVM, wysyłając sygnał do uruchomionego procesu. Uwaga: nie należy tego używać SIGSEGV, ponieważ Hotspot przechwytuje ten sygnał i w większości miejsc ponownie wyrzuca go jako wyjątek NullPointerException. Dlatego lepiej wysłać SIGBUSnp.
Jeśli utworzysz proces wątku, który nieskończenie odradza więcej wątków (które odradzają więcej wątków, które ...) ostatecznie spowoduje błąd przepełnienia stosu w samej JVM.
To dało mi wyjście (po 5 minutach uważaj na swojego barana)
An unrecoverable stack overflow has occurred.## A fatal error has been detected by the JavaRuntimeEnvironment:## EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000000070e53ed7, pid=12840, tid=0x0000000000101078## JRE version:Java(TM) SE RuntimeEnvironment(8.0_144-b01)(build 1.8.0_144-b01)#Java VM:JavaHotSpot(TM)64-BitServer VM (25.144-b01 mixed mode windows-amd64 compressed oops)#Problematic frame:#
Jeśli przez „awarię” masz na myśli nagłe przerwanie pracy maszyny JVM, na przykład w wyniku czego JVM zapisuje do swojego hs_err_pid% p.log , możesz to zrobić w ten sposób.
Ustaw argument-Xmx na niewielką wartość i powiedz JVM, aby wymusił awarię przy braku pamięci:
-Xmx10m-XX:+CrashOnOutOfMemoryError
Dla jasności, bez drugiego argumentu powyżej, spowodowałoby to po prostu zakończenie działania jvm przez OutOfMemoryError, ale nie spowodowałoby "awarii" ani nagłego przerwania działania jvm.
Technika ta okazała się pomocna, gdy próbowałem przetestować argument JVM -XX: ErrorFile, który kontroluje, gdzie taki dziennik hs_err_pid powinien zostać zapisany. Znalazłem ten post tutaj, próbując znaleźć sposoby na wymuszenie takiej awarii. Kiedy później stwierdziłem, że powyższe działa jako najłatwiejsze dla moich potrzeb, chciałem dodać je do listy tutaj.
Wreszcie, FWIW, jeśli ktokolwiek może to przetestować, gdy ma już ustawioną wartość -Xms w twoich argumentach (do jakiejś większej wartości niż powyżej), będziesz chciał to również usunąć lub zmienić, albo nie dostaniesz awarii, ale po prostu błąd uruchomienia jvm powodujący zgłoszenie „Początkowa wielkość sterty ustawiona na wartość większą niż maksymalna wielkość sterty”. (Nie byłoby to oczywiste, gdyby uruchomiono maszynę JVM jako usługę, na przykład w przypadku niektórych serwerów aplikacji. Ponownie, ugryzło mnie to, więc chciałem się tym podzielić.)
Robię to teraz, ale nie do końca wiem, jak ... :-) JVM (i moja aplikacja) czasami po prostu znikają. Nie wyrzucono żadnych błędów, nic nie zostało zarejestrowane. Przechodzi od pracy do całkowitego braku działania natychmiast bez ostrzeżenia.
Zacznij sprawdzać swój sprzęt, szczególnie pamięć!
Thorbjørn Ravn Andersen
Niestety, jest na wielu komputerach, które inaczej działają dobrze. Robi to tylko ta jedna konkretna aplikacja (i nie wymaga ona dużej ilości pamięci ani procesora).
Brian Knoblauch
0
Najkrótsza? Użyj klasy Robot, aby wywołać CTRL + BREAK. Zauważyłem to, gdy próbowałem zamknąć program bez zamykania konsoli (nie miał funkcji „wyjścia”).
Stare pytanie - mam nadzieję, że w przyszłości ktoś skorzysta na Twojej odpowiedzi.
dbmitch
0
Czy to się liczy?
long pid =ProcessHandle.current().pid();try{Runtime.getRuntime().exec("kill -9 "+pid);}catch(Exception e){}
Działa tylko dla Linuksa i Java 9.
Z jakiegoś powodu nie dostaję, ProcessHandle.current().destroyForcibly();nie zabija JVM i wyrzuca java.lang.IllegalStateExceptionz komunikatem zniszczenie bieżącego procesu niedozwolone .
Odpowiedzi:
Najbliższą pojedynczą „odpowiedzią” jest
System.exit()
natychmiastowe zamknięcie maszyny JVM bez odpowiedniego czyszczenia. Ale poza tym najbardziej prawdopodobnymi odpowiedziami są kod natywny i wyczerpanie zasobów. Alternatywnie możesz poszukać w module śledzenia błędów firmy Sun błędów w Twojej wersji maszyny JVM, z których niektóre pozwalają na powtarzalne scenariusze awarii. Kiedyś otrzymywaliśmy pół-regularne awarie, gdy zbliżaliśmy się do limitu pamięci 4 Gb w wersjach 32-bitowych (zwykle używamy teraz 64-bitów).źródło
Nie nazwałbym wyrzucania OutOfMemoryError lub StackOverflowError awarią. To są zwykłe wyjątki. Aby naprawdę zawiesić maszynę wirtualną, istnieją 3 sposoby:
W przypadku ostatniej metody mam krótki przykład, który spowoduje ładną awarię maszyny wirtualnej Sun Hotspot:
Prowadzi to do przepełnienia stosu w GC, więc nie otrzymasz StackOverflowError, ale prawdziwy błąd, w tym plik hs_err *.
źródło
java.lang.OutOfMemoryError: GC overhead limit exceeded
JNI . W rzeczywistości w przypadku JNI zawieszanie się jest domyślnym trybem działania. Musisz bardzo ciężko pracować, aby się nie zawiesił.
źródło
Użyj tego:
Ta klasa musi znajdować się w ścieżce startowej klasy, ponieważ używa zaufanego kodu, więc uruchom w ten sposób:
źródło
Field f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );
dla mnie zadziałało świetnie.Unsafe
jest z definicji „niebezpieczny”. To trochę oszustwo.getDeclaredField
sztuczki w JDK 8u131 na Linux x64, w tym produkcjęhs_err_pid*.log
z plikuSIGSEGV
.Unsafe
nie jest oszustwem. OP nie szuka „czystego” rozwiązania problemu programistycznego. Potrzebuje jvm do awarii w najbrzydszy możliwy sposób. Robienie paskudnych, rodzimych rzeczy jest tym, co może do tego doprowadzić, i właśnie takUnsafe
jest.Przyszedłem tutaj, ponieważ natknąłem się na to pytanie w The Passionate Programmer autorstwa Chada Fowlera. Dla tych, którzy nie mają dostępu do kopii, pytanie to jest traktowane jako rodzaj filtru / testu dla kandydatów przeprowadzających rozmowy kwalifikacyjne na stanowisko wymagające „naprawdę dobrych programistów Java”.
W szczególności pyta:
Programuję w Javie od ponad 15 lat i uznałem to pytanie za zagadkowe i niesprawiedliwe. Jak zauważyli inni, Java, jako język zarządzany, została specjalnie zaprojektowana, aby nie ulegać awariom . Oczywiście zawsze są błędy JVM, ale:
Jak wspominali inni, część kodu natywnego za pośrednictwem JNI to pewny sposób na awarię środowiska JRE. Ale autor wyraźnie wspomniał w czystej Javie , więc to się skończyło.
Inną opcją byłoby podanie fałszywych kodów bajtowych środowiska JRE; dość łatwo jest zrzucić trochę śmieciowych danych binarnych do pliku .class i poprosić środowisko JRE o jego uruchomienie:
To się liczy? Mam na myśli to, że samo środowisko JRE nie uległo awarii; poprawnie wykrył fałszywy kod, zgłosił go i zakończył pracę.
To pozostawia nam najbardziej oczywiste rodzaje rozwiązań, takie jak przepuszczanie stosu przez rekurencję, wyczerpywanie się pamięci sterty przez alokacje obiektów lub po prostu rzucanie
RuntimeException
. Ale to po prostu powoduje zamknięcie środowiska JRE zStackOverflowError
lub podobnym wyjątkiem, co ponownie nie jest tak naprawdę awarią .Więc co zostało? Bardzo chciałbym usłyszeć, co autor miał na myśli jako właściwe rozwiązanie.
Aktualizacja : odpowiedział tutaj Chad Fowler .
PS: to poza tym świetna książka. Podniosłem go dla moralnego wsparcia podczas nauki Rubiego.
źródło
Ten kod spowoduje awarię maszyny JVM w nieprzyjemny sposób
źródło
InternalError
JDK 1.8. JVM już nie zawodzi.Ostatni raz, gdy próbowałem, zrobił to:
Pierwsza część wygenerowanego pliku dziennika:
źródło
Idealna implementacja JVM nigdy nie ulegnie awarii.
Aby zawiesić maszynę JVM, oprócz JNI, musisz znaleźć błąd w samej maszynie wirtualnej. Nieskończona pętla po prostu zużywa procesor. Nieskończone przydzielanie pamięci powinno po prostu powodować błędy OutOfMemoryError w dobrze zbudowanej JVM. Prawdopodobnie spowodowałoby to problemy dla innych wątków, ale dobra JVM nadal nie powinna ulec awarii.
Jeśli możesz znaleźć błąd w kodzie źródłowym maszyny wirtualnej i na przykład spowodować błąd segmentacji w wykorzystaniu pamięci przez implementację maszyny wirtualnej, możesz ją faktycznie zawiesić.
źródło
Jeśli chcesz zawiesić maszynę JVM - użyj w Sun JDK 1.6_23 lub niższej:
Wynika to z błędu w Sun JDK - znalezionego również w OpenJDK. Jest to naprawione od Oracle JDK 1.6_24 i nowszych.
źródło
Zależy, co masz na myśli mówiąc o wypadku.
Możesz wykonać nieskończoną rekurencję, aby zabrakło miejsca na stosie, ale to się zawiesi "wdzięcznie". Dostaniesz wyjątek, ale sama maszyna JVM będzie obsługiwać wszystko.
Możesz również użyć JNI do wywołania kodu natywnego. Jeśli nie zrobisz tego dobrze, możesz sprawić, że się zawiesi. Debugowanie tych awarii jest „zabawne” (zaufaj mi, musiałem napisać dużą bibliotekę DLL C ++, którą wywołujemy z podpisanego apletu java). :)
źródło
Książka Java Virtual Machine autorstwa Jona Meyera zawiera przykład serii instrukcji kodu bajtowego, które spowodowały zrzut pamięci JVM. Nie mogę znaleźć mojej kopii tej książki. Jeśli ktoś tam ma, poszukaj go i opublikuj odpowiedź.
źródło
na winxpsp2 w / wmp10 jre6.0_7
Desktop.open (uriToAviOrMpgFile)
Powoduje to, że pojawiający się wątek rzuca niewyłapany przedmiot do rzucania i powoduje awarię hotspotu
YMMV
źródło
Zepsuty sprzęt może spowodować awarię dowolnego programu. Kiedyś miałem powtarzalną awarię aplikacji na konkretnym komputerze, podczas gdy działała dobrze na innych komputerach z dokładnie taką samą konfiguracją. Okazuje się, że maszyna miała wadliwą pamięć RAM.
źródło
najkrótsza możliwa droga :)
źródło
Exception in thread "main" java.lang.StackOverflowError at Test.main
. Używam jdk1.8.0_65Nie awaria, ale bliżej awarii niż akceptowana odpowiedź użycia
System.exit
Możesz zatrzymać JVM, dzwoniąc
Runtime.getRuntime().halt( status )
Według dokumentów: -
źródło
tutaj jest szczegółowe wyjaśnienie, co powoduje zrzut pamięci JVM (tj. awarię): http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534
źródło
Jeśli chcesz udawać, że zabrakło Ci pamięci, możesz to zrobić
Znam kilka sposobów spowodowania zrzucenia przez maszynę JVM pliku błędu przez wywołanie metod natywnych (takich, które są wbudowane), ale prawdopodobnie najlepiej nie wiesz, jak to zrobić. ;)
źródło
Jeśli zdefiniujesz awarię jako przerwanie procesu z powodu nieobsługiwanej sytuacji (tj. Braku wyjątku Java lub błędu), nie można tego zrobić z poziomu Javy (chyba że masz uprawnienia do używania klasy sun.misc.Unsafe). To cały punkt zarządzanego kodu.
Typowe awarie w kodzie natywnym zdarzają się przez usuwanie odniesień do niewłaściwych obszarów pamięci (adres zerowy lub niewłaściwie wyrównany). Innym źródłem mogą być nielegalne instrukcje maszynowe (kody operacyjne) lub nieobsłużone sygnały z wywołań biblioteki lub jądra. Oba mogą zostać wyzwolone, jeśli JVM lub biblioteki systemowe zawierają błędy.
Na przykład kod JITed (wygenerowany), metody natywne lub wywołania systemowe (sterownik grafiki) mogą mieć problemy prowadzące do rzeczywistych awarii (dość często dochodziło do awarii, gdy korzystałeś z funkcji ZIP i zabrakło im pamięci). W takich przypadkach program obsługi awarii maszyny JVM włącza się i zrzuca stan. Może również wygenerować plik rdzenia systemu operacyjnego (Dr. Watson w systemie Windows i zrzut rdzenia na * nix).
W systemie Linux / Unix możesz łatwo spowodować awarię JVM, wysyłając sygnał do uruchomionego procesu. Uwaga: nie należy tego używać
SIGSEGV
, ponieważ Hotspot przechwytuje ten sygnał i w większości miejsc ponownie wyrzuca go jako wyjątek NullPointerException. Dlatego lepiej wysłaćSIGBUS
np.źródło
JNI jest dużym źródłem awarii. Możesz także zawiesić się przy użyciu interfejsu JVMTI, ponieważ musi on być również napisany w C / C ++.
źródło
Jeśli utworzysz proces wątku, który nieskończenie odradza więcej wątków (które odradzają więcej wątków, które ...) ostatecznie spowoduje błąd przepełnienia stosu w samej JVM.
To dało mi wyjście (po 5 minutach uważaj na swojego barana)
źródło
Jeśli przez „awarię” masz na myśli nagłe przerwanie pracy maszyny JVM, na przykład w wyniku czego JVM zapisuje do swojego hs_err_pid% p.log , możesz to zrobić w ten sposób.
Ustaw argument-Xmx na niewielką wartość i powiedz JVM, aby wymusił awarię przy braku pamięci:
Dla jasności, bez drugiego argumentu powyżej, spowodowałoby to po prostu zakończenie działania jvm przez OutOfMemoryError, ale nie spowodowałoby "awarii" ani nagłego przerwania działania jvm.
Technika ta okazała się pomocna, gdy próbowałem przetestować argument JVM -XX: ErrorFile, który kontroluje, gdzie taki dziennik hs_err_pid powinien zostać zapisany. Znalazłem ten post tutaj, próbując znaleźć sposoby na wymuszenie takiej awarii. Kiedy później stwierdziłem, że powyższe działa jako najłatwiejsze dla moich potrzeb, chciałem dodać je do listy tutaj.
Wreszcie, FWIW, jeśli ktokolwiek może to przetestować, gdy ma już ustawioną wartość -Xms w twoich argumentach (do jakiejś większej wartości niż powyżej), będziesz chciał to również usunąć lub zmienić, albo nie dostaniesz awarii, ale po prostu błąd uruchomienia jvm powodujący zgłoszenie „Początkowa wielkość sterty ustawiona na wartość większą niż maksymalna wielkość sterty”. (Nie byłoby to oczywiste, gdyby uruchomiono maszynę JVM jako usługę, na przykład w przypadku niektórych serwerów aplikacji. Ponownie, ugryzło mnie to, więc chciałem się tym podzielić.)
źródło
Jeśli zmienisz tę nieskończoną pętlę for na rekurencyjne wywołanie tej samej funkcji, otrzymasz wyjątek przepełnienia stosu:
źródło
Robię to teraz, ale nie do końca wiem, jak ... :-) JVM (i moja aplikacja) czasami po prostu znikają. Nie wyrzucono żadnych błędów, nic nie zostało zarejestrowane. Przechodzi od pracy do całkowitego braku działania natychmiast bez ostrzeżenia.
źródło
Najkrótsza? Użyj klasy Robot, aby wywołać CTRL + BREAK. Zauważyłem to, gdy próbowałem zamknąć program bez zamykania konsoli (nie miał funkcji „wyjścia”).
źródło
Czy to się liczy?
Działa tylko dla Linuksa i Java 9.
Z jakiegoś powodu nie dostaję,
ProcessHandle.current().destroyForcibly();
nie zabija JVM i wyrzucajava.lang.IllegalStateException
z komunikatem zniszczenie bieżącego procesu niedozwolone .źródło
Napotykam ten problem podczas próby replikacji awarii maszyny JVM.
Jni działa, ale należy go dostosować do różnych platform. Ostatecznie używam tej kombinacji, aby spowodować awarię JVM
-XX:+CrashOnOutOfMemoryError
long[] l = new long[Integer.MAX_VALUE];
aby wywołać OOMNastępnie JVM ulegnie awarii i wygeneruje dziennik awarii.
źródło
Jeśli 'Crash' jest czymś, co przerywa działanie jvm / programu od normalnego zakończenia, to może to zrobić wyjątek nieobsługiwany.
Więc to zależy od typu CRASH ?!
źródło
ArithmeticException
jest