1. Ottenere una traccia dello stack
Il linguaggio di programmazione Java offre a un programmatore molti modi per ottenere informazioni su ciò che sta accadendo in un programma. E non solo parole.
Ad esempio, dopo che i programmi C++ sono stati compilati, diventano un file di grandi dimensioni pieno di codice macchina e tutto ciò che è disponibile per un programmatore in fase di esecuzione è l'indirizzo del blocco di memoria che contiene il codice macchina attualmente in esecuzione. Non molto, diciamo.
Ma per Java, anche dopo che un programma è stato compilato, le classi rimangono classi, i metodi e le variabili non scompaiono e il programmatore ha molti modi per ottenere informazioni su ciò che sta accadendo nel programma.
Traccia dello stack
Ad esempio, in un punto dell'esecuzione di un programma, puoi scoprire la classe e il nome del metodo attualmente in esecuzione. E non solo un metodo: puoi ottenere informazioni sull'intera catena di chiamate di metodo dal metodo corrente al main()
metodo.
Un elenco che consiste nel metodo corrente, nel metodo che lo ha richiamato e nel metodo che lo ha chiamato, ecc. è chiamato stack trace . Puoi ottenerlo con questa dichiarazione:
StackTraceElement[] methods = Thread.currentThread().getStackTrace();
Puoi anche scriverlo in due righe:
Thread current = Thread.currentThread();
StackTraceElement[] methods = current.getStackTrace();
Il metodo statico currentThread()
della Thread
classe restituisce un riferimento a un Thread
oggetto, che contiene informazioni sul thread corrente, ovvero il thread corrente di esecuzione. Imparerai di più sui thread nei livelli 17 e 18 della ricerca Java Core .
Questo Thread
oggetto ha un getStackTrace()
metodo, che restituisce un array di StackTraceElement
oggetti, ognuno dei quali contiene informazioni su un metodo. Presi insieme, tutti questi elementi formano una traccia dello stack .
Esempio:
Codice |
---|
|
Uscita console |
|
Come possiamo vedere nell'output della console dell'esempio, il getStackTrace()
metodo ha restituito un array di tre elementi:
getStackTrace()
metodo dellaThread
classetest()
metodo dellaMain
classemain()
metodo dellaMain
classe
Da questa traccia dello stack, possiamo concludere che:
- Il
Thread.getStackTrace()
metodo è stato chiamato dalMain.test()
metodo alla riga 11 del file Main.java - Il
Main.test()
metodo è stato chiamato dalMain.main()
metodo alla riga 5 del file Main.java - Nessuno ha chiamato il
Main.main()
metodo: questo è il primo metodo nella catena di chiamate.
A proposito, sullo schermo sono state visualizzate solo alcune delle informazioni disponibili. Tutto il resto può essere ottenuto direttamente StackTraceElement
dall'oggetto
2.StackTraceElement
Come suggerisce il nome, la StackTraceElement
classe è stata creata per memorizzare informazioni su un elemento di traccia dello stack , ovvero un metodo nel stack trace
.
Questa classe ha i seguenti metodi di istanza:
Metodo | Descrizione |
---|---|
|
Restituisce il nome della classe |
|
Restituisce il nome del metodo |
|
Restituisce il nome del file (un file può contenere più classi) |
|
Restituisce il numero di riga nel file in cui è stato chiamato il metodo |
|
Restituisce il nome del modulo (può essere null ) |
|
Restituisce la versione del modulo (può essere null ) |
Possono aiutarti a ottenere informazioni più complete sullo stack di chiamate corrente:
Codice | Uscita console | Nota |
---|---|---|
|
|
nome classe nome metodo nome file numero riga nome modulo versione modulo nome classe nome metodo nome file numero riga nome modulo versione modulo nome classe nome metodo nome file numero riga nome modulo versione modulo |
3. Impila
Sai già cos'è una traccia dello stack , ma cos'è uno stack (classe Stack)?
Uno stack è una struttura di dati a cui è possibile aggiungere elementi e da cui è possibile recuperare elementi. Così facendo, puoi prendere solo gli elementi dalla fine: prendi prima l'ultimo aggiunto, poi il penultimo aggiunto, ecc.
La stessa pila di nomi suggerisce questo comportamento, come il modo in cui interagiresti con una pila di fogli. Se metti in pila i fogli 1, 2 e 3, devi recuperarli in ordine inverso: prima il terzo foglio, poi il secondo e solo dopo il primo.
Java ha anche una speciale classe di raccolta Stack con lo stesso nome e comportamento. Questa classe condivide molti comportamenti con ArrayList
e LinkedList
. Ma ha anche metodi che implementano il comportamento dello stack:
Metodi | Descrizione |
---|---|
|
Aggiunge l' obj elemento in cima allo stack |
|
Prende l'elemento dalla cima della pila (la profondità della pila diminuisce) |
|
Restituisce l'elemento in cima alla pila (la pila non cambia) |
|
Controlla se la raccolta è vuota |
|
Cerca un oggetto nella raccolta e lo restituisceindex |
Esempio:
Codice | Contenuto della pila (la parte superiore della pila è a destra) |
---|---|
|
|
Gli stack sono usati abbastanza spesso nella programmazione. Quindi questa è una raccolta utile.
4. Visualizzazione di un'analisi dello stack durante la gestione delle eccezioni
Perché un elenco di chiamate di metodo è chiamato traccia dello stack ? Perché se pensi all'elenco dei metodi come a una pila di fogli di carta con i nomi dei metodi, quando chiami il metodo successivo, aggiungi un foglio con il nome di quel metodo alla pila. E il foglio di carta successivo va oltre, e così via.
Quando un metodo termina, il foglio in cima alla risma viene rimosso. Non è possibile rimuovere un foglio dal centro della risma senza rimuovere tutti i fogli sopra di esso. Analogamente, non è possibile terminare un metodo nel mezzo di una catena di chiamate senza terminare tutti i metodi che ha chiamato.
Eccezioni
Un altro uso interessante degli stack è durante la gestione delle eccezioni.
Quando si verifica un errore in un programma e viene generata un'eccezione , l'eccezione contiene l' analisi dello stack corrente , un array costituito da un elenco di metodi che iniziano, dal metodo principale e terminano con il metodo in cui si è verificato l'errore. C'è anche la linea in cui è stata lanciata l'eccezione!
Questa traccia dello stack è memorizzata all'interno dell'eccezione e può essere facilmente recuperata da essa utilizzando il seguente metodo:StackTraceElement[] getStackTrace()
Esempio:
Codice | Nota |
---|---|
|
Rileva l'eccezione Ottieni l'analisi dello stack che esisteva quando si è verificato l'errore. |
Questo è un metodo della Throwable
classe, quindi tutti i suoi discendenti (cioè tutte le eccezioni) hanno il getStackTrace()
metodo. Super conveniente, eh?
Visualizza l'analisi dello stack dell'eccezione
A proposito, la Throwable
classe ha un altro metodo per lavorare con le tracce dello stack, un metodo che visualizza tutte le informazioni sulla traccia dello stack memorizzate all'interno dell'eccezione. Si chiama printStackTrace()
.
Abbastanza convenientemente, puoi chiamarlo su qualsiasi eccezione.
Esempio:
Codice |
---|
|
Uscita console |
|
GO TO FULL VERSION