1. Få en stabelsporing

Får et stabelspor

Programmeringsspråket Java tilbyr mange måter for en programmerer å få informasjon om hva som skjer i et program. Og ikke bare ord.

For eksempel, etter at C++-programmer er kompilert, blir de én stor fil full av maskinkode, og alt som er tilgjengelig for en programmerer ved kjøring er adressen til minneblokken som inneholder maskinkoden som kjøres for øyeblikket. Ikke mye, la oss si.

Men for Java, selv etter at et program er kompilert, forblir klasser klasser, metoder og variabler forsvinner ikke, og programmereren har mange måter å få informasjon om hva som skjer i programmet.

Stabelspor

For eksempel, på et tidspunkt i et programs kjøring, kan du finne ut klassen og navnet på metoden som kjøres for øyeblikket. Og ikke bare én metode - du kan få informasjon om hele kjeden av metodekall fra gjeldende metode tilbake til metoden main().

En liste som består av den gjeldende metoden, og metoden som påkalte den, og metode som kalte den, osv. kalles en stack trace . Du kan få det med denne uttalelsen:

StackTraceElement[] methods = Thread.currentThread().getStackTrace();

Du kan også skrive det som to linjer:

Thread current = Thread.currentThread();
StackTraceElement[] methods = current.getStackTrace();

Klassens statiske currentThread()metode Threadreturnerer en referanse til et Threadobjekt, som inneholder informasjon om gjeldende tråd, dvs. gjeldende utførelsestråd. Du vil lære mer om tråder på nivå 17 og 18 i Java Core -oppdraget.

Dette Threadobjektet har en getStackTrace()metode som returnerer en rekke StackTraceElementobjekter, som hver inneholder informasjon om en metode. Til sammen danner alle disse elementene et stabelspor .

Eksempel:

Kode
public class Main
{
   public static void main(String[] args)
   {
      test();
   }

   public static void test()
   {
      Thread current = Thread.currentThread();
      StackTraceElement[] methods = current.getStackTrace();

      for(var info: methods)
         System.out.println(info);
   }
}
Konsollutgang
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)

Som vi kan se i eksemplets konsollutgang, getStackTrace()returnerte metoden en rekke med tre elementer:

  • getStackTrace()Threadklassens metode
  • test()Mainklassens metode
  • main()Mainklassens metode

Fra dette stabelsporet kan vi konkludere med at:

  • Metoden Thread.getStackTrace()ble kalt av Main.test()metoden på linje 11 i Main.java-filen
  • Metoden Main.test()ble kalt av Main.main()metoden på linje 5 i Main.java-filen
  • Ingen kalte Main.main()metoden - dette er den første metoden i kjeden av samtaler.

Forresten, bare noe av den tilgjengelige informasjonen ble vist på skjermen. Alt annet kan fås direkte fra StackTraceElementobjektet



2.StackTraceElement

Som navnet antyder, StackTraceElementble klassen opprettet for å lagre informasjon om et stacksporingselement , dvs. én metode i stack trace.

Denne klassen har følgende instansmetoder:

Metode Beskrivelse
String getClassName()
Returnerer navnet på klassen
String getMethodName()
Returnerer navnet på metoden
String getFileName()
Returnerer navnet på filen (en fil kan inneholde flere klasser)
int getLineNumber()
Returnerer linjenummeret i filen der metoden ble kalt
String getModuleName()
Returnerer navnet på modulen (dette kan være null)
String getModuleVersion()
Returnerer versjonen av modulen (dette kan være null)

De kan hjelpe deg med å få mer fullstendig informasjon om gjeldende anropsstabel:

Kode Konsollutgang Merk
public class Main
{
   public static void main(String[] args)
   {
      test();
   }

   public static void test()
   {
      Thread current = Thread.currentThread();
      StackTraceElement[] methods = current.getStackTrace();

      for(StackTraceElement info: methods)
      {
         System.out.println(info.getClassName());
         System.out.println(info.getMethodName());

         System.out.println(info.getFileName());
         System.out.println(info.getLineNumber());

         System.out.println(info.getModuleName());
         System.out.println(info.getModuleVersion());
         System.out.println();
      }
   }
}
java.lang.Thread
getStackTrace
Thread.java
1606
java.base
11.0.2

Main
test
Main.java
11
null
null

Main
main
Main.java
5
null
null
klassenavn
metodenavn
filnavn
linjenummer
modulnavn
modulversjon

klassenavn
metodenavn
filnavn
linjenummer
modulnavn
modulversjon

klassenavn
metodenavn
filnavn
linjenummer
modulnavn
modulversjon


3. Stable

Du vet allerede hva en stabelsporing er, men hva er en stabel (stabelklasse)?

En stack er en datastruktur som du kan legge til elementer i og som du kan hente elementer fra. Når du gjør det, kan du bare ta elementer fra slutten: du tar først den siste som ble lagt til, deretter den nest siste som ble lagt til, osv.

Selve navnebunken antyder denne oppførselen, som hvordan du vil samhandle med en bunke med papirer. Hvis du legger ark 1, 2 og 3 i en stabel, må du hente dem i omvendt rekkefølge: først det tredje arket, så det andre, og først så det første.

Java har til og med en spesiell Stack-samlingsklasse med samme navn og oppførsel. Denne klassen deler mye atferd med ArrayListog LinkedList. Men den har også metoder som implementerer stabeladferd:

Metoder Beskrivelse
T push(T obj)
Legger objelementet til toppen av stabelen
T pop()
Tar elementet fra toppen av stabelen (stabeldybden reduseres)
T peek()
Returnerer elementet øverst i stabelen (stabelen endres ikke)
boolean empty()
Sjekker om samlingen er tom
int search(Object obj)
Søker etter et objekt i samlingen og returnerer detindex

Eksempel:

Kode Stabelinnhold (toppen av stabelen er til høyre)
Stack<Integer> stack = new Stack<Integer>();
stack.push(1);
stack.push(2);
stack.push(3);
int x = stack.pop();
stack.push(4);
int y = stack.peek();
stack.pop();
stack.pop();

[1]
[1, 2]
[1, 2, 3]
[1, 2]
[1, 2, 4]
[1, 2, 4]
[1, 2]
[1]

Stabler brukes ganske ofte i programmering. Så dette er en nyttig samling.



4. Vise et stabelspor under unntakshåndtering

Hvorfor kalles en liste over metodekall en stabelsporing ? For hvis du tenker på listen over metoder som en bunke med papirark med metodenavn, så når du kaller neste metode, legger du til et ark med den metodens navn til stabelen. Og det neste arket går på toppen av det, og så videre.

Når en metode avsluttes, fjernes arket på toppen av stabelen. Du kan ikke fjerne et ark fra midten av stabelen uten å fjerne alle arkene over det. På samme måte kan du ikke avslutte en metode midt i en samtalekjede uten å avslutte alle metodene den har kalt.

Unntak

En annen interessant bruk for stabler er under unntakshåndtering.

Når det oppstår en feil i et program og et unntak blir kastet , inneholder unntaket gjeldende stabelsporing - en matrise som består av en liste over metoder som starter, fra hovedmetoden og slutter med metoden der feilen oppstod. Det er til og med linjen der unntaket ble kastet!

Denne stabelsporingen er lagret i unntaket og kan enkelt hentes fra den ved å bruke følgende metode:StackTraceElement[] getStackTrace()

Eksempel:

Kode Merk
try
{
   // An exception may occur here
}
catch(Exception e)
{
   StackTraceElement[] methods = e.getStackTrace()
}




Fang unntaket

Få stabelsporet som eksisterte da feilen oppstod.

Dette er en metode av Throwableklassen, så alle dens etterkommere (dvs. alle unntak) har metoden getStackTrace(). Super praktisk, ikke sant?

Vis unntakets stabelsporing

Klassen har forresten Throwableen annen metode for å jobbe med stabelspor, en metode som viser all stabelsporingsinformasjon som er lagret i unntaket. Det kalles printStackTrace().

Ganske praktisk kan du kalle det på ethvert unntak.

Eksempel:

Kode
try
{
   // An exception may occur here
}
catch(Exception e)
{
   e.printStackTrace();
}
Konsollutgang
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)