JavaRush /Blog Java /Random-PL /Stack Trace i to, z czym jest spożywany
Alukard
Poziom 37
London

Stack Trace i to, z czym jest spożywany

Opublikowano w grupie Random-PL
W tym artykule dowiesz się i zrozumiesz, jak działa zjawisko Java StackTrace, znane również jako Call Stack Tracing. Informacje te zostały opracowane z myślą o początkujących, którzy zetknęli się z tą koncepcją na początku 9. poziomu składni języka Java. Myślę, że każdy z Was przynajmniej raz spotkał się z podobnymi błędami podczas pracy w swoim IDE, niezależnie od tego, czy był to Idea , Eclipse , czy coś innego.
Exception in thread "main" java.lang.ArithmeticException
	at com.example.task01.Test.division(Test.java:10)
	at com.example.task01.Test.main(Test.java:6)
Jak można się domyślić, jest to nasz trop. Ale nie spiesz się z paniką, teraz omówimy dla Ciebie ten przykład. Najpierw musisz zrozumieć fakt, że StackTracedziała to tak, jak Стэкsugeruje jego nazwa. W tym momencie zajmiemy się nieco bardziej szczegółowo. Jak działa kolekcja Stack Na ósmym poziomie zapoznałeś się już ze zbiorami i wiesz, że są one podzielone na trzy grupy Set- zbiór, List- lista, Map- słownik (lub mapa). Według JavaRush (c). Nasz Stackjest częścią tej grupy List. Zasadę jego działania można określić jako LIFO , co oznacza Last In First Out. Mianowicie jest to lista przypominająca stos książek; aby wziąć element, który umieściliśmy jako Stackpierwszy, musimy najpierw wyodrębnić wszystkie elementy, które dodaliśmy do naszej listy później. Jak widać na powyższym obrazku, w odróżnieniu od np. zwykłej listy, ArrayListgdzie dowolny element z listy możemy pobrać po indeksie. Jeszcze raz dla wzmocnienia. Pobranie elementu z Стэкаjest możliwe tylko od końca! Natomiast pierwszy dodany do niego element znajduje się na początku (lub na dole, jak wygodniej). Oto metody, jakie ma nasz Stack Obiekt push()- Dodaje element na górę stosu. Obiekt pop()— zwraca element znajdujący się na szczycie stosu, usuwając go przy tym. Obiekt peek()— zwraca element znajdujący się na szczycie stosu, ale go nie usuwa. int search()– Wyszukuje element na stosie. Jeśli zostanie znaleziony, zwracane jest jego przesunięcie od góry stosu. W przeciwnym razie zwracane jest -1. boolean empty()— Sprawdza, czy stos jest pusty. Zwraca wartość true, jeśli stos jest pusty. Zwraca wartość false, jeśli stos zawiera elementy. Po co więc taki, który Javajest StackTracezbudowany na zasadach działania Stack? Spójrzmy na poniższy przykład błędu, który wystąpił podczas wykonywania tak prostego programu.
public class Test {

    public static void main(String[] args) {
        System.out.println(convertStringToInt(null));
    }

    public static int convertStringToInt(String s) {
        int x = Integer.parseInt(s);
        return x;
    }
}
Mamy klasę Testz dwiema metodami. Każdy jest znany maini convertStringToIntjego logika polega na konwersji i zwróceniu ciągu znaków otrzymanego z zewnątrz (czyli z metody main) na liczbę całkowitą typu int. Jak widać celowo przekazaliśmy parametr zamiast ciągu znaków z jakąś liczbą null. Nasza metoda nie mogła poprawnie przetworzyć tego parametru i spowodowała błąd NumberFormatException. Jak wiadomo program zaczyna wykonywać swoją pracę od metody maini w tym momencie tworzy nową Стэкo nazwie gdzie pod cyfrą 1StackTrace wstawia aktualną wartość swojej pracy , następnie przechodzimy do metody i programu jeszcze raz wpisze parametry naszej lokalizacji do utworzonej wcześniej pod numerem 2 , wówczas nazywa się to metodą niewidzialną dla naszych oczu znajdującą się w klasie i będzie to już nasz element numer 3 , w tej metodzie zostanie dodane kolejne wywołanie wewnętrzne do numeru 4 , aby sprawdzić, czy element ma wartość null , co doprowadzi do błędu. Program musi wyświetlić nasz błąd wskazując cały łańcuch naszych przejść aż do wystąpienia błędu. Tu z pomocą przychodzi jej ta wcześniej utworzona z danymi naszych przejść . convertStringToIntStackTraceparseIntIntegerStackTraceStackTraceStackTrace
Exception in thread "main" java.lang.NumberFormatException: null
	at java.base/java.lang.Integer.parseInt(Integer.java:614)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at com.example.task01.Test.convertStringToInt(Solution.java:10)
	at com.example.task01.Test.main(Solution.java:6)
Zanim pojawił się błąd, program zagłębił się w metody, ale gdy tylko pojawił się błąd, wszystko zaczyna się dziać w odwrotnej kolejności. Wydrukowana zostanie linia opisująca problem (w przykładzie nr 1), następnie zostanie pobrana ostatnia (i na górze) wartość dodana do naszej, Стэкbyła to liczba czwarta i wypisana do konsoli (w przykładzie nr 2) i widzimy, że problem pojawił się w klasie Integerw linii kodu 614 i nazwał tę linię linią 770 metody parseInttej samej klasy (nr 3 w przykładzie), która po dodaniu Стэкbyła numerem trzy i tą metodą klasy, Integernadal dla nas niewidoczna, została już wywołana przez naszą metodę convertStringToIntznajdującą się w linii 10 naszego programu (nr 4 w przykładzie, a przy dodawaniu była druga), a ta z kolei została wywołana mainw linii 6 (nr 5 w przykładzie i odpowiednio podczas dodawania pierwszego). Tak więc, przechowując Стекkrok po kroku wywoływane przez nas metody, mogliśmy powrócić do mainrównoległego drukowania informacji, które dokładnie doprowadziły nas do błędu. Ale StackTraceto nie tylko praca z błędami, pozwala nam uzyskać wiele ciekawych informacji na temat procesu naszej aplikacji. Spójrzmy na inny popularny przykład w komentarzach do wykładu głównego poziomu 9. Mamy kod i od razu dołączę do niego obrazek wizualizujący przebieg programu:
public class Test {
    public static void main(String[] args) {
        method1();
        method2();
    }
    public static void method1() {
        //не вызывает ничего
    }
    public static void method2() {
        method3();
        method4();
    }
    public static void method3() {
        //не вызывает ничего
    }
    public static void method4() {
        method5();
    }
    public static void method5() {
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        for (StackTraceElement element:stackTraceElements) {
            System.out.println(element.getMethodName());
        }
    }
}
Stack Trace i z czym jest spożywany - 2 Tutaj nasz program wykonuje swoje zadanie bezbłędnie i kończy się. Oto, co zobaczymy w wynikach konsoli:
getStackTrace
method5
method4
method2
main

Process finished with exit code 0
Jak doszliśmy do tego wniosku i co się stało w piątej metodzie, zaczynając od wiersza 20? Obawiam się, że najlepsze, co mogę zrobić, to dodać najpopularniejsze wyjaśnienie (w skrócie) użytkownika Kirilla z komentarzy do wykładu. Przejdźmy do linii tworzenia StackTracei przeanalizujmy ją element po elemencie:
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement[]- wskazanie typu tablicy (na wczesnych poziomach poznałeś już tablice takie jak int[], String[], tutaj jest tak samo). stackTraceElements- nazwa tablicy może być dowolna, biorąc pod uwagę ogólne zasady nazewnictwa, nie ma to wpływu na pracę. Thread.currentThread()- uzyskanie linku do bieżącego wątku, w którym wykonywane są metody, które chcemy śledzić (na razie to nie jest istotne, wątki przeanalizujesz dokładniej na poziomie 16 w zadaniu Java Core) getStackTrace()- otrzymujemy wszystkie Стэкwywołane metody (To jest zwykły getter dla StackTrace) Zobaczmy teraz, co Utworzona tablica może nam się przydać. Rozumiemy, że tablica przechowuje informacje o wykonanych metodach. (c) I w tym celu w 21. linijce uruchamiamy zmodyfikowany cykl foro nazwie forEach(swoją drogą, tym, którzy jeszcze tego cyklu nie przestudiowali, radzę o tym poczytać) i wyprowadzamy dane z tablicy do konsoli , czyli informację o tym , jakimi metodami zastosowano się podczas prac z wykorzystaniem konstrukcji element.getMethodName(). Uwaga, jak widzimy, elementem zerowym tablicy okazał się getStackTrace()odpowiednio on sam, ponieważ w momencie otrzymania tablicy danych była to ostatnia metoda, która została wykonana i tym samym znalazła się na górze Стэкаi pamiętając o naszej konstrukcji „ Last in, First out ” jest natychmiast pierwszym, który zostanie dodany do tablicy pod elementem zerowym. Oto, co jeszcze możemy uzyskać z StackTraceElement: String getClassName()- Zwraca nazwę klasy. String getMethodName()— Zwraca nazwę metody. String getFileName()- Zwraca nazwę pliku (w jednym pliku może znajdować się wiele klas). String getModuleName()- Zwraca nazwę modułu (może mieć wartość null). String getModuleVersion()- Zwraca wersję modułu (może mieć wartość null). int getLineNumber()- Zwraca numer linii w pliku, w którym wywołano metodę. Teraz, gdy rozumiesz już ogólną zasadę działania, radzę ci samemu wypróbować różne metody StackTracew swoim Ide . Nawet jeśli nie opanowałeś wszystkiego do końca, kontynuuj naukę, a zagadka ułoży się tak samo, jak u mnie w tej kwestii. Życzę wszystkim sukcesów! Ps Jeśli spodobał Ci się ten materiał, wesprzyj go lajkiem. Nie jest to dla ciebie trudne, miło mi. Dziękuję i do zobaczenia na poziomie 41 ;)
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION