Stack trace

Java Syntax Pro
14 уровень , 5 лекция
Открыта

1. Получение стек-трейса

Получение стек-трейса

В языке программирования Java у программиста есть очень много способов получить информацию о том, что сейчас происходит в программе. И это не просто слова.

Например, программы на языке C++ после компиляции превращаются в один большой файл машинного кода и все, что во время выполнения доступно программисту, — это адрес куска памяти, который содержит машинный код, который сейчас выполняется. Не густо, скажем так.

В Java же, даже после компиляции, классы остаются классами, методы и переменные никуда не деваются, и у программиста есть много способов получить данные о том, что сейчас происходит в программе.

Стек-трейс

Например, в любой момент работы программы можно узнать класс и имя метода, который сейчас выполняется. И даже не одного метода, а получить информацию о всей цепочке вызовов методов от текущего метода до метода main().

Список, состоящий из текущего метода, метода, который его вызвал, его вызвавшего метода и т.д., называется stack trace. Получить его можно с помощью команды:

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

Можно записать ее и в две строки:

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

Статический метод currentThread() класса Thread возвращает ссылку на объект типа Thread, который содержит информацию о текущей нити (о текущем потоке выполнения). Подробнее о нитях вы узнаете в квесте Java Core.

У этого объекта Thread есть метод getStackTrace(), который возвращает массив элементов StackTraceElement, каждый из которых содержит информацию об одном методе. Все элементы вместе и образуют stack trace.

Пример:

Код
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);
   }
}
Вывод на экран
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)

Как мы видим по выводу на экран, в приведенном примере метод getStackTrace() вернул массив из трех элементов:

  • Метод getStackTrace() класса Thread
  • Метод test() класса Main
  • Метод main() класса Main

Из этого стек-трейса можно сделать вывод, что:

  • Метод Thread.getStackTrace() был вызван методом Main.test() в строке 11 файла Main.java
  • Метод Main.test() был вызван методом Main.main() в строке 5 файла Main.java
  • Метод Main.main() никто не вызывал — это первый метод в цепочке вызовов.

Кстати, на экране отобразилась только часть всей имеющийся информации. Все остальное можно получить прямо из объекта StackTraceElement



2. StackTraceElement

Класс StackTraceElement, как следует из его названия, создан для того, чтобы хранить информацию по одному элементу stack trace — т.е. по одному методу из StackTrace.

У объектов этого класса есть такие методы:

Метод Описание
String getClassName()
Возвращает имя класса
String getMethodName()
Возвращает имя метода
String getFileName()
Возвращает имя файла (в одном файле может быть много классов)
int getLineNumber()
Возвращает номер строки в файле, в которой был вызов метода
String getModuleName()
Возвращает имя модуля (может быть null)
String getModuleVersion()
Возвращает версию модуля (может быть null)

С их помощью можно получить более полную информацию о текущем стеке вызовов:

Код Вывод на экран Примечание
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
имя класса
имя метода
имя файла
номер строки
имя модуля
версия модуля

имя класса
имя метода
имя файла
номер строки
имя модуля
версия модуля

имя класса
имя метода
имя файла
номер строки
имя модуля
версия модуля


3. Стек

Что такое Stack Trace вы уже знаете, а что же такое сам Stack (Стек)?

Стек — это структура хранения данных, в которую можно добавлять элементы и из которой можно забирать элементы. Причем брать элементы можно только с конца: сначала последний добавленный, потом — предпоследний, и т.д.

Само название Stack переводится с английского как «стопка» и очень похоже на стопку бумаги. Если вы положите на стопку бумаги листы 1, 2 и 3, взять вы их сможете только в обратном порядке: сначала третий, затем второй, а только затем первый.

В Java даже есть специальная коллекция с таким поведением и таким же названием — Stack. Этот класс в своем поведении очень похож на ArrayList и LinkedList.  Однако у него есть еще методы, которые реализуют поведение стека:

Методы Описание
T push(T obj)
Добавляет элемент obj в конец списка (наверх стопки)
T pop()
Забирает элемент с верха стопки (высота стопки уменьшается)
T peek()
Возвращает элемент с верха стопки (стопка не меняется)
boolean empty()
Проверяет, не пуста ли коллекция
int search(Object obj)
Ищет объект из коллекции, возвращает его index

Пример:

Код Содержимое стека (вершина справа)
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]

Стек используется в программировании довольно часто. Так что это полезная коллекция.



4. Вывод стек-трейса при обработке ошибок

Почему же список вызовов методов назвали StackTrace? Да потому, что если представить список методов в виде стопки листов с именами методов, при вызове очередного метода на эту стопку кладется лист с именем метода, на него — следующий, и т.д.

Когда метод завершается, лист с верха стопки удаляется. Нельзя удалить лист из середины стопки, не удалив все листы, лежащие в нем — нельзя прекратить работу метода в цепочке вызовов, не завершив все методы, вызванные им.

Исключения

Еще одно интересное применение стека — обработка исключений.

Когда в программе происходит ошибка и создается исключение, в него записывается текущий stack trace: массив, состоящий из списка методов начиная с метода main и заканчивая методом, где произошла ошибка. Там даже есть строка, в которой было создано исключение!

Этот stack trace ошибки хранится внутри исключения и может быть легко извлечен из нее с помощью метода: StackTraceElement[] getStackTrace()

Пример:

Код Примечание
try
{
   // тут может возникнуть исключение
}
catch(Exception e)
{
   StackTraceElement[] methods = e.getStackTrace()
}




Захватываем исключение

Получаем из него стек-трейс в момент возникновения ошибки.

Это метод класса Throwable, а значит, все его классы-наследники (т.е. вообще все исключения), имеют метод getStackTrace(). Очень удобно, не так ли?

Печать стек-трейса ошибки

Кстати, у класса Throwable есть еще один метод для работы со stack-trace: он выводит в консоль всю информацию по stack trace, который хранится внутри исключения. Он так и называется printStackTrace().

Вызвать его можно у любого исключения, что очень удобно.

Пример:

Код
try
{
   // тут может возникнуть исключение
}
catch(Exception e)
{
   e.printStackTrace();
}
Вывод на экран
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)


Комментарии (257)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
KarinaShineofKornflower Уровень 32
9 июля 2026
ну, всяко лучше, чем просто книгу читать
KarinaShineofKornflower Уровень 32
9 июля 2026
насыщенно логикой
Валерка Ферум Уровень 32
24 апреля 2026
Если тоже считаешь, что stack нужно знать и понимать, лайкай пост. Посмотрим сколько нас;)
Grigoryvvv Уровень 26 Expert
23 марта 2026
23.03.2026 / 15 уровень

1. Здесь метод getStackTrace() класса Throwable
try
{
   // тут может возникнуть исключение
}
catch(Exception e)
{
   StackTraceElement[] methods = e.getStackTrace()
}

  

2. Здесь метод getStackTrace() класса Thread

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


Здесь два разных метода getStackTrace() — один принадлежит Throwable, другой Thread. Главное отличие: - e.getStackTrace(); Стек создастся только при возникновении исключения и покажет всю историю до того места, где произошла авария - Thread.currentThread().getStackTrace(); Мы сами получаем текущее представление стека, что бы посмотреть текущую цепочку вызовов методов до данной строки в текущем потоке выполнения. Стоит заметить, что стек вызовов потока уже существует сам по себе всегда, мы просто берем из него данные. 3. Коллекция Stack Класс коллекции Stack - это обычная коллекция. Она ни как не связана с e.getStackTrace() или Thread.currentThread().getStackTrace();, ни наследованием, ни интерфейсом, вообще ни как. Её запихали в эту лекцию, потому что у неё концепция построения структуры такая же, как и у стека StackTrace. Только ни кто ничего не объяснил, как обычно.
Artem Уровень 1
5 марта 2026
какая то фигня ваще, это пригодится хоть?
Сайфер Уровень 51
5 июня 2026
Хахаххахаха... БВАХАХАХАХАХХААХ!!!!!!
Rei Уровень 32
31 января 2026

Стек используется в программировании довольно часто. Так что это полезная коллекция.
Здесь для ясности полезно пояснить, что стек как структура данных используется постоянно, но сам класс Stack в Java считается устаревшим и его не рекомендуется использовать в новом коде. Oracle прямо пишет: Use Deque instead of Stack. Пример стандартной замены Stack в Java - Deque:

Deque<Integer> stack = new ArrayDeque<>();

stack.push(1);
stack.push(2);
stack.push(3);

int x = stack.pop();   // 3
int y = stack.peek(); // 2
Итог: Стек как концепция - ✅ используется постоянно java.util.Stack - ⚠️устаревший дизайн Современная замена - ✅ Deque / ArrayDeque
C0N5P1RACY Уровень 42
24 декабря 2025
Коротко об этой лекции: - так так так так так так так, понятно? - ... UP: Ладно, чуть разобравшись все более менее стало понятнее
I'll kick them all Уровень 5
27 июля 2025
Какой-то древний JDK=). У списка даже нет методов getFirst(), addFirst(). Так и пойми почему не принимает сервер. Всю статистику запорол.
Никита Уровень 1
25 июля 2025
Задачу "стек в домашних условиях" решил просто, заменив:

private final List<String> storage = new LinkedList<>();
на:

private final LinkedList<String> storage = new LinkedList<>();
А у класса LinkedList все необходимые методы уже реализованы. Возможно, если создатели задачи предполагали, что нам нужно самостоятельно переписать методы push(), pop() и остальные, то лучше добавить условие в требованиях к задаче, что тип переменной storage менять запрещено. А то я не понял этого сразу :)
Anonymous #3585174 Уровень 33
10 июля 2025
like