1. Mendapatkan jejak tindanan

Mendapat jejak tindanan

Bahasa pengaturcaraan Java menawarkan banyak cara untuk pengaturcara mendapatkan maklumat tentang apa yang berlaku dalam program. Dan bukan hanya kata-kata.

Sebagai contoh, selepas program C++ disusun, ia menjadi satu fail besar yang penuh dengan kod mesin, dan semua yang tersedia untuk pengaturcara semasa masa jalan ialah alamat blok memori yang mengandungi kod mesin yang sedang dilaksanakan. Tidak banyak, katakan.

Tetapi untuk Java, walaupun selepas program disusun, kelas kekal sebagai kelas, kaedah dan pembolehubah tidak hilang, dan pengaturcara mempunyai banyak cara untuk mendapatkan maklumat tentang perkara yang berlaku dalam atur cara.

Jejak tindanan

Sebagai contoh, pada titik dalam pelaksanaan program, anda boleh mengetahui kelas dan nama kaedah yang sedang dilaksanakan. Dan bukan hanya satu kaedah — anda boleh mendapatkan maklumat tentang keseluruhan rangkaian panggilan kaedah daripada kaedah semasa kembali kepada kaedah main().

Senarai yang terdiri daripada kaedah semasa, dan kaedah yang menggunakan kaedah itu, dan kaedah yang memanggilnya, dsb. dipanggil surih tindanan . Anda boleh mendapatkannya dengan kenyataan ini:

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

Anda juga boleh menulisnya sebagai dua baris:

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

currentThread()Kaedah statik Threadkelas mengembalikan rujukan kepada Threadobjek, yang mengandungi maklumat tentang utas semasa, iaitu utas pelaksanaan semasa. Anda akan mengetahui lebih lanjut tentang urutan dalam Tahap 17 dan 18 pencarian Java Core .

ThreadObjek ini mempunyai getStackTrace()kaedah, yang mengembalikan tatasusunan StackTraceElementobjek, setiap satunya mengandungi maklumat tentang kaedah. Jika digabungkan, semua elemen ini membentuk jejak tindanan .

Contoh:

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

Seperti yang dapat kita lihat dalam output konsol contoh, getStackTrace()kaedah itu mengembalikan tatasusunan tiga elemen:

  • getStackTrace()kaedah Threadkelas
  • test()kaedah Mainkelas
  • main()kaedah Mainkelas

Daripada jejak tindanan ini, kita boleh membuat kesimpulan bahawa:

  • Kaedah ini Thread.getStackTrace()dipanggil oleh Main.test()kaedah pada baris 11 fail Main.java
  • Kaedah ini Main.test()dipanggil oleh Main.main()kaedah pada baris 5 fail Main.java
  • Tiada siapa yang memanggil Main.main()kaedah itu — ini adalah kaedah pertama dalam rangkaian panggilan.

By the way, hanya beberapa maklumat yang ada dipaparkan pada skrin. Segala-galanya boleh diperolehi terus dari StackTraceElementobjek



2.StackTraceElement

Seperti namanya, StackTraceElementkelas telah dicipta untuk menyimpan maklumat tentang unsur surih tindanan , iaitu satu kaedah dalam stack trace.

Kelas ini mempunyai kaedah contoh berikut:

Kaedah Penerangan
String getClassName()
Mengembalikan nama kelas
String getMethodName()
Mengembalikan nama kaedah
String getFileName()
Mengembalikan nama fail (satu fail boleh mengandungi berbilang kelas)
int getLineNumber()
Mengembalikan nombor baris dalam fail tempat kaedah dipanggil
String getModuleName()
Mengembalikan nama modul (ini boleh null)
String getModuleVersion()
Mengembalikan versi modul (ini boleh null)

Mereka boleh membantu anda mendapatkan maklumat yang lebih lengkap tentang timbunan panggilan semasa:

Kod Output konsol Catatan
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
nama kelas
kaedah nama fail
nama
baris nombor
modul nama
modul versi

nama kelas
kaedah
nama fail nama
baris nombor modul nama modul versi nama kelas nama kaedah nama fail baris nombor modul nama modul versi










3. Timbunan

Anda sudah tahu apa itu surih tindanan , tetapi apakah tindanan (kelas tindanan)?

Tindanan ialah struktur data yang mana anda boleh menambah elemen dan daripada mana anda boleh mendapatkan semula elemen. Dengan berbuat demikian, anda hanya boleh mengambil elemen dari penghujung: anda mula-mula mengambil yang terakhir ditambah, kemudian yang kedua ke yang terakhir ditambah, dsb.

Timbunan nama itu sendiri mencadangkan tingkah laku ini, seperti cara anda berinteraksi dengan timbunan kertas. Jika anda meletakkan helaian 1, 2 dan 3 dalam timbunan, anda perlu mendapatkannya dalam susunan terbalik: pertama helaian ketiga, kemudian helaian kedua, dan hanya kemudian helaian pertama.

Java juga mempunyai kelas koleksi Stack khas dengan nama dan tingkah laku yang sama. Kelas ini berkongsi banyak tingkah laku dengan ArrayListdan LinkedList. Tetapi ia juga mempunyai kaedah yang melaksanakan tingkah laku tindanan:

Kaedah Penerangan
T push(T obj)
Menambah objelemen ke bahagian atas timbunan
T pop()
Mengambil elemen dari bahagian atas tindanan (kedalaman tindanan berkurangan)
T peek()
Mengembalikan item di bahagian atas timbunan (timbunan tidak berubah)
boolean empty()
Menyemak sama ada koleksi kosong
int search(Object obj)
Mencari objek dalam koleksi dan mengembalikannyaindex

Contoh:

Kod Kandungan tindanan (bahagian atas tindanan berada di sebelah kanan)
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]

Tindanan digunakan agak kerap dalam pengaturcaraan. Jadi ini adalah koleksi yang berguna.



4. Memaparkan surih tindanan semasa pengendalian pengecualian

Mengapakah senarai panggilan kaedah dipanggil jejak tindanan ? Kerana jika anda memikirkan senarai kaedah sebagai timbunan helaian kertas dengan nama kaedah, maka apabila anda memanggil kaedah seterusnya, anda menambah helaian dengan nama kaedah itu pada timbunan. Dan helaian kertas seterusnya diletakkan di atasnya, dan seterusnya.

Apabila kaedah tamat, helaian di bahagian atas tindanan dikeluarkan. Anda tidak boleh mengeluarkan helaian dari tengah tindanan tanpa mengeluarkan semua helaian di atasnya. Begitu juga, anda tidak boleh menamatkan kaedah di tengah-tengah rangkaian panggilan tanpa menamatkan semua kaedah yang telah dipanggil.

Pengecualian

Satu lagi kegunaan yang menarik untuk tindanan adalah semasa pengendalian pengecualian.

Apabila ralat berlaku dalam atur cara dan pengecualian dilemparkan , pengecualian mengandungi surih tindanan semasa — tatasusunan yang terdiri daripada senarai kaedah bermula, daripada kaedah utama dan berakhir dengan kaedah di mana ralat berlaku. Malah terdapat garis di mana pengecualian dilemparkan!

Surih tindanan ini disimpan di dalam pengecualian dan boleh diperoleh dengan mudah daripadanya menggunakan kaedah berikut:StackTraceElement[] getStackTrace()

Contoh:

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




Tangkap pengecualian

Dapatkan surih tindanan yang wujud apabila ralat berlaku.

Ini ialah kaedah kelas Throwable, jadi semua keturunannya (iaitu semua pengecualian) mempunyai getStackTrace()kaedah itu. Sangat mudah, ya?

Paparkan surih tindanan pengecualian

Dengan cara ini, Throwablekelas mempunyai kaedah lain untuk bekerja dengan surih tindanan, kaedah yang memaparkan semua maklumat surih tindanan yang disimpan di dalam pengecualian. Ia dipanggil printStackTrace().

Agak mudah, anda boleh memanggilnya pada sebarang pengecualian.

Contoh:

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