JavaRush /Java Blog /Random-IT /Stack Trace e con cosa viene mangiato
Alukard
Livello 37
London

Stack Trace e con cosa viene mangiato

Pubblicato nel gruppo Random-IT
In questo articolo imparerai e capirai come funziona il fenomeno Java StackTrace, noto anche come Call Stack Tracing. Queste informazioni sono state strutturate per i principianti che hanno incontrato questo concetto all'inizio della sintassi Java livello 9. Penso che tutti voi, almeno una volta, abbiate riscontrato errori simili lavorando nel vostro IDE, indipendentemente dal fatto che fosse Idea , Eclipse o qualcos'altro.
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)
Questo, come avrai intuito, è il nostro tracciato. Ma non farti prendere dal panico, ora analizzeremo questo esempio per te. Per prima cosa devi capire il fatto che StackTracefunziona come Стэкsuggerisce il nome. A questo punto ci soffermeremo un po’ più nel dettaglio. Come funziona la raccolta Stack All'ottavo livello, hai già conosciuto le raccolte e sai che sono divise in tre gruppi Set: set, List- elenco, Map- dizionario (o mappa). Secondo JavaRush (c). Il nostro Stackfa parte del gruppo List. Il principio del suo funzionamento può essere descritto come LIFO , che sta per Last In First Out. Si tratta cioè di una lista simile ad una pila di libri; per poter prendere l'elemento che abbiamo inserito per Stackprimo, dobbiamo prima estrarre tutti gli elementi che abbiamo aggiunto successivamente alla nostra lista. Come indicato nell'immagine sopra, a differenza, ad esempio, di una lista normale ArrayListin cui possiamo ottenere qualsiasi elemento dalla lista tramite indice. Ancora una volta per rinforzo. Ottenere un elemento da Стэкаè possibile solo dalla fine! Mentre il primo elemento aggiunto si trova all'inizio (o in fondo, come è più conveniente). Questi sono i metodi del nostro Stack oggetto push(): aggiunge un elemento in cima allo stack. Oggetto pop(): restituisce l'elemento in cima allo stack, rimuovendolo nel processo. Oggetto peek(): restituisce l'elemento in cima allo stack, ma non lo rimuove. int search(): cerca un elemento nello stack. Se trovato, viene restituito il suo offset dalla cima dello stack. Altrimenti viene restituito -1. booleano empty(): controlla se lo stack è vuoto. Restituisce vero se lo stack è vuoto. Restituisce false se lo stack contiene elementi. Allora perché ne hai Javabisogno StackTracedi uno basato sui principi di funzionamento Stack? Di seguito consideriamo l'esempio di un errore che si è verificato durante l'esecuzione di un programma così semplice.
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;
    }
}
Abbiamo una classe Testcon due metodi. Tutti lo conoscono maine convertStringToIntla logica è quella di convertire e restituire una stringa ricevuta dall'esterno (cioè dal metodo main) in un numero intero di tipo int. Come puoi vedere, abbiamo passato intenzionalmente il parametro invece di una stringa con un numero null. Il nostro metodo non è riuscito a elaborare correttamente questo parametro e ha causato un errore NumberFormatException. Come sai, il programma inizia a elaborare il suo lavoro dal metodo maine in questo momento ne crea uno nuovo Стэкcon un nome StackTracedove mette il valore attuale del suo lavoro sotto il numero 1 , poi torniamo al metodo convertStringToInte al programma inserisce i parametri della nostra posizione in quello creato prima StackTracesotto il numero 2 , poi si chiama un metodo invisibile ai nostri occhi parseIntche si trova nella classe Integere questo sarà già il nostro elemento numero 3StackTrace , in questo metodo verrà aggiunta un'altra chiamata interna al StackTracenumero 4 per verificare la presenza di null nell'elemento che porterà a un errore. Il programma deve visualizzare il nostro errore indicando l'intera catena delle nostre transizioni fino al verificarsi dell'errore. È qui che viene in suo aiuto quello precedentemente creato con i dati delle nostre transizioni StackTrace.
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)
Prima che si verificasse l'errore, il programma ha approfondito i metodi, ma non appena si è verificato l'errore, tutto inizia ad accadere nell'ordine inverso. Viene stampata una riga che descrive il problema (N° 1 nell'esempio), poi viene preso l'ultimo (e in alto) valore aggiunto al nostro, Стэкera il numero quattro e stampato sulla console (N° 2 nell'esempio) e vediamo che il problema è sorto nella classe Integeralla riga di codice 614 e abbiamo chiamato questa riga, riga 770 di un metodo parseIntdella stessa classe (n. 3 nell'esempio) che, una volta aggiunto, Стэкera il numero tre e questo metodo di classe, Integerancora non visibile a noi, era già stato chiamato dal nostro metodo convertStringToIntsituato alla riga 10 del nostro programma (n. 4 nell'esempio, e quando lo aggiungevamo era il secondo), e, a sua volta, è stato chiamato mainalla riga 6 (n. 5 nell'esempio e in fase di aggiunta rispettivamente il primo). Quindi, memorizzando Стекpasso dopo passo i nostri metodi chiamati, siamo stati in grado di tornare alla mainstampa parallela delle informazioni che ci hanno portato esattamente all'errore. Ma StackTracequesto non funziona solo con gli errori, ci consente di ottenere molte informazioni interessanti sul processo della nostra richiesta. Diamo un'occhiata a un altro esempio popolare nei commenti alla lezione principale del livello 9. Abbiamo il codice e vi allegherò subito un'immagine che visualizza il processo del programma:
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 e con cosa si mangia - 2 Qui il nostro programma fa il suo lavoro in modo impeccabile e finisce. Questo è ciò che vedremo nell'output della console:
getStackTrace
method5
method4
method2
main

Process finished with exit code 0
Come siamo arrivati ​​a questa conclusione e cosa è successo nel quinto metodo, a partire dalla riga 20? Temo che la cosa migliore che posso fare sia aggiungere la spiegazione più popolare (abbreviata) dell'utente Kirill dai commenti alla conferenza. Passiamo alla linea di creazione StackTracee analizziamola elemento per elemento:
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement[]- un'indicazione del tipo di array (ai primi livelli hai già imparato a conoscere gli array come int[], String[], qui è lo stesso). stackTraceElements- il nome dell'array può essere qualsiasi cosa, tenendo conto delle regole generali di denominazione, ciò non influisce sul lavoro. Thread.currentThread()- ottenere un collegamento al thread corrente in cui vengono eseguiti i metodi che vogliamo tracciare (per ora questo non è importante, analizzerai i thread in modo più dettagliato al livello 16 nella ricerca Java Core) getStackTrace()- otteniamo tutti Стэкi metodi chiamati (Questo è un normale getter per StackTrace) Ora vediamo cosa può esserci utile l'array creato. Comprendiamo che l'array memorizza informazioni sui metodi eseguiti. (c) E per questo, nella 21a riga, lanciamo un ciclo modificato forchiamato forEach(a proposito, per coloro che non hanno ancora studiato questo ciclo, ti consiglio di leggerlo) e trasmettiamo i dati dall'array alla console , vale a dire informazioni su quali metodi sono stati eseguiti durante i lavori utilizzando la costruzione element.getMethodName(). Attenzione, come vediamo, l'elemento zero dell'array si è rivelato essere se stesso, getStackTrace()rispettivamente, poiché al momento della ricezione dell'array di dati era l'ultimo metodo eseguito e quindi è finito in alto Стэка, e ricordando la nostra costruzione “ Last in, first out ” è immediatamente il primo ad essere aggiunto all'array sotto l'elemento zero. Ecco cos'altro possiamo ottenere da StackTraceElement: String getClassName()- Restituisce il nome della classe. String getMethodName(): restituisce il nome del metodo. String getFileName(): restituisce il nome del file (possono esserci molte classi in un file). String getModuleName(): restituisce il nome del modulo (può essere null). String getModuleVersion(): restituisce la versione del modulo (può essere null). int getLineNumber()- Restituisce il numero di riga nel file in cui è stato chiamato il metodo. Ora che hai compreso il principio generale di funzionamento, ti consiglio di provare tu stesso diversi metodi StackTracenel tuo Ide . Anche se non hai padroneggiato completamente tutto, continua ad imparare e il puzzle si risolverà nello stesso modo in cui si è rivelato per me in questa materia. Vi auguro tutto il successo! Ps Se ti è piaciuto questo materiale, supportalo con un mi piace. Non è difficile per te, mi fa piacere. Grazie e ci vediamo al livello 41 ;)
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION