1. Een stacktracering verkrijgen

Een stacktracering ophalen

De programmeertaal Java biedt een programmeur vele manieren om informatie te krijgen over wat er in een programma gebeurt. En niet alleen woorden.

Nadat bijvoorbeeld C++-programma's zijn gecompileerd, worden ze één groot bestand vol machinecode, en het enige dat tijdens runtime beschikbaar is voor een programmeur is het adres van het geheugenblok dat de machinecode bevat die momenteel wordt uitgevoerd. Niet veel zullen we maar zeggen.

Maar voor Java blijven klassen, zelfs nadat een programma is gecompileerd, klassen, verdwijnen methoden en variabelen niet en heeft de programmeur veel manieren om informatie te krijgen over wat er in het programma gebeurt.

Stapel traceren

Op een bepaald moment tijdens de uitvoering van een programma kunt u bijvoorbeeld de klasse en naam achterhalen van de methode die momenteel wordt uitgevoerd. En niet slechts één methode - u kunt informatie krijgen over de hele keten van methodeaanroepen van de huidige methode terug naar de main()methode.

Een lijst die bestaat uit de huidige methode en de methode die deze heeft aangeroepen, en de methode die deze heeft aangeroepen, enz. wordt een stacktracering genoemd . Je kunt het krijgen met deze verklaring:

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

Je kunt het ook als twee regels schrijven:

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

De statische currentThread()methode van de Threadklasse retourneert een verwijzing naar een Threadobject, dat informatie bevat over de huidige thread, dwz de huidige uitvoeringsthread. Je leert meer over threads in niveau 17 en 18 van de Java Core- zoektocht.

Dit Threadobject heeft een getStackTrace()methode, die een reeks StackTraceElementobjecten retourneert, die elk informatie over een methode bevatten. Samen vormen al deze elementen een stacktracering .

Voorbeeld:

Code
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);
   }
}
Console-uitvoer
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)

Zoals we kunnen zien in de console-uitvoer van het voorbeeld, getStackTrace()retourneerde de methode een array van drie elementen:

  • getStackTrace()werkwijze van de Threadklas
  • test()werkwijze van de Mainklas
  • main()werkwijze van de Mainklas

Uit deze stacktrace kunnen we concluderen dat:

  • De Thread.getStackTrace()methode werd aangeroepen door de Main.test()methode op regel 11 van het bestand Main.java
  • De Main.test()methode werd aangeroepen door de Main.main()methode op regel 5 van het bestand Main.java
  • Niemand heeft de Main.main()methode aangeroepen — dit is de eerste methode in de keten van aanroepen.

Overigens werd slechts een deel van de beschikbare informatie op het scherm weergegeven. StackTraceElementAl het andere kan rechtstreeks van het object worden verkregen



2.StackTraceElement

Zoals de naam al doet vermoeden, StackTraceElementis de klasse gemaakt om informatie op te slaan over een stacktrace- element, dwz één methode in het stack trace.

Deze klasse heeft de volgende instantiemethoden:

Methode Beschrijving
String getClassName()
Retourneert de naam van de klasse
String getMethodName()
Retourneert de naam van de methode
String getFileName()
Retourneert de naam van het bestand (één bestand kan meerdere klassen bevatten)
int getLineNumber()
Retourneert het regelnummer in het bestand waar de methode werd aangeroepen
String getModuleName()
Retourneert de naam van de module (dit kan zijn null)
String getModuleVersion()
Retourneert de versie van de module (dit kan null)

Ze kunnen u helpen meer volledige informatie te krijgen over de huidige call-stack:

Code Console-uitvoer Opmerking
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
klassenaam
methodenaam
bestandsnaam
regelnummer
modulenaam
moduleversie

klassenaam
methodenaam
bestandsnaam
regelnummer modulenaam moduleversie klassenaam methodenaam bestandsnaam regelnummer
modulenaam moduleversie









3. Stapelen

U weet al wat een stacktrace is, maar wat is een stack (Stack-klasse)?

Een stapel is een gegevensstructuur waaraan u elementen kunt toevoegen en waaruit u elementen kunt ophalen. Daarbij kun je alleen elementen van het einde nemen: je neemt eerst de laatst toegevoegde, dan de op een na laatste toegevoegde, etc.

De naamstapel zelf suggereert dit gedrag, zoals hoe je zou omgaan met een stapel papieren. Als je bladen 1, 2 en 3 op een stapel legt, moet je ze in omgekeerde volgorde terughalen: eerst het derde blad, dan het tweede en dan pas het eerste.

Java heeft zelfs een speciale Stack-verzamelklasse met dezelfde naam en hetzelfde gedrag. Deze klas deelt veel gedragingen met ArrayListen LinkedList. Maar het heeft ook methoden die stapelgedrag implementeren:

methoden Beschrijving
T push(T obj)
Voegt het objelement toe aan de bovenkant van de stapel
T pop()
Neemt het element van de bovenkant van de stapel (de stapeldiepte neemt af)
T peek()
Retourneert het item bovenaan de stapel (de stapel verandert niet)
boolean empty()
Controleert of de verzameling leeg is
int search(Object obj)
Zoekt naar een object in de verzameling en geeft het terugindex

Voorbeeld:

Code Stapelinhoud (de bovenkant van de stapel bevindt zich aan de rechterkant)
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]

Stapels worden vrij vaak gebruikt bij het programmeren. Dit is dus een nuttige verzameling.



4. Een stacktracering weergeven tijdens het afhandelen van uitzonderingen

Waarom wordt een lijst met methodeaanroepen een stacktrace genoemd ? Want als je de lijst met methoden ziet als een stapel vellen papier met methodenamen, dan voeg je bij het aanroepen van de volgende methode een blad met de naam van die methode toe aan de stapel. En het volgende vel papier komt daar bovenop, enzovoort.

Wanneer een methode eindigt, wordt het vel bovenaan de stapel verwijderd. U kunt geen vel uit het midden van de stapel halen zonder alle vellen erboven te verwijderen. Evenzo kunt u een methode niet midden in een aanroepketen beëindigen zonder alle aangeroepen methoden te beëindigen.

Uitzonderingen

Een ander interessant gebruik van stapels is tijdens het afhandelen van uitzonderingen.

Wanneer er een fout optreedt in een programma en er een uitzondering wordt gegenereerd , bevat de uitzondering de huidige stacktraceringeen array die bestaat uit een lijst met methoden die begint bij de hoofdmethode en eindigt met de methode waar de fout is opgetreden. Er is zelfs de lijn waar de uitzondering werd gegooid!

Deze stacktracering wordt binnen de uitzondering opgeslagen en kan er eenvoudig uit worden opgehaald met behulp van de volgende methode:StackTraceElement[] getStackTrace()

Voorbeeld:

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




Vang de uitzondering

Haal de stacktracering op die bestond toen de fout optrad.

Dit is een methode van de Throwableklasse, dus al zijn afstammelingen (dwz alle uitzonderingen) hebben de getStackTrace()methode. Superhandig toch?

Geef de stacktracering van de uitzondering weer

Overigens Throwableheeft de klasse een andere methode om met stacktraceringen te werken, een methode die alle stacktrace-informatie weergeeft die in de uitzondering is opgeslagen. Het wordt genoemd printStackTrace().

Heel handig, je kunt het op elke uitzondering noemen.

Voorbeeld:

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