StackTrace

Открыта
StackTrace - 1

— Привет! Сегодня я расскажу тебе, что такое стек-трейс. Но сначала расскажу, что такое стек.

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

В Java для этого есть специальная коллекция – Stack. Это коллекция, у которой есть методы «добавить элемент» и «взять(достать/забрать) элемент». Как ты уже догадался, первым будет взят элемент, добавленный самым последним.

— Хм. Вроде не сложно и понятно.

— Отлично. Тогда сейчас объясню, что такое стек-трейс.

— Представь себе, что в Java функция А вызвала функцию Б, а та вызвала функцию В, а та, в свою очередь, функцию Г. Так вот, чтобы выйти из функции Б, нужно сначала выйти из функции В, а для этого выйти из функции Г. Это очень похоже на стек.

— А чем похоже?

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

— Ну, некоторая аналогия есть, но не уверен, что я все понял правильно.

— Смотри. Стек – это набор элементов. Как листы в стопке. Чтобы взять третий сверху лист, надо сначала взять второй, а для этого взять первый. Класть и брать листы можно всегда, но всегда взять можно только самый верхний.

— С вызовом функций то же самое. Функция А вызывает функцию Б, а та вызывает функцию В. И чтобы выйти из А, надо сначала выйти из Б, а для этого надо выйти из В.

— Подожди. Если я все правильно понял, то весь этот стек сведется к «взять можно только самый последний положенный лист», «выйти можно только из последней функции, в которую зашли». Так?

— Да. Так вот – последовательность вызовов функций — это и есть «стек вызовов функций», он же просто «стек вызовов». Функция, вызванная последней, должна завершиться самой первой. Давай посмотрим это на примере:

Получение и вывод текущего стека вызовов:
public class ExceptionExample
{
  public static void main(String[] args)
  {
    method1();
  }

  public static void method1()
  {
    method2();
  }

  public static void method2()
  {
    method3();
  }

  public static void method3()
  {
    StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
    for (StackTraceElement element : stackTraceElements)
    {
       System.out.println(element.getMethodName());
    }
  }
}
Вот какой результат мы получим:
getStackTrace
method3
method2
method1
main
10
Задача
Java Syntax,  9 уровень,  1 лекция
Недоступна
Набираем код
Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. Вот почему во время обучения в секретном центре JavaRush вы иногда встречаете задания на набор кода. Набирая код, вы привыкаете к синтаксису и зарабатываете немного материи. А ещё — боретесь с ленью.

— Ок. С вызовом функций похоже все понятно. А что это еще за StackTraceElement?

— Java-машина ведет запись всех вызовов функций. У нее есть для этого специальная коллекция – стек. Когда одна функция вызывает другую, Java-машина помещает в этот стек новый элемент StackTraceElement. Когда функция завершается этот элемент удаляется из стека. Таким образом, в этом стеке всегда хранится актуальная информация о текущем состоянии «стека вызовов функций».

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

— В примере выше ты можешь видеть демонстрацию этого дела:

1) Получаем «стек вызовов»:

2) Проходимся по нему с помощью цикла for-each. Надеюсь, ты его еще не забыл.

3) Печатаем в System.out имена методов.

— Интересная штука и, похоже, совсем не сложная. Спасибо, Риша!

Комментарии (81)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Ваня Бойко12 уровень, Киев
12 апреля, 14:33
Thread.currentThread() - получает ссылку на текущий поток. getStackTrace() - получает весь стек вызовов. В результате получаем мы массив StackTraceElement[].
эволюта13 уровень
3 апреля, 07:27
Охренительно объяснили, Шилдт просто нервно курит в сторонке... пошел гуглить и курить литературу.Еще полдня возни...
Павел13 уровень, Санкт-Петербург
3 апреля, 21:51
все норм, StackTraceElement - тут хранятся типо записи getMethodName - а тут мы их просто читаем. то есть мы не можем посмотреть на документ которого у нас нет. так вот, StackTraceElement - он нам дает документ, getMethodName - а этот чувак разрешает не только держать его у себя в руках но еще и посмотреть что там, и все по сути то
Maria Gregory15 уровень
25 марта, 23:02
Почему в выводе нет
getMethodName()
- ведь этот метод был вызван последним.
Павел13 уровень, Санкт-Петербург
3 апреля, 21:53
вот все норм, последний как положенно
Alexey Yagudin15 уровень, Санкт-Петербург
10 марта, 11:22
Класс называется: пример исключения. А остальное норм)))
Alexey Yagudin15 уровень, Санкт-Петербург
10 марта, 18:46
Потом становится понятно, почему)))
Михаил19 уровень, Москва
5 марта, 03:48
задачка "Набираем код" не работет че-то
Валерий15 уровень
7 марта, 07:39
Я сам с ней промучился. Проверил каждую букву, ошибок нет, а светится красным. В итоге скопировал код из статьи и тогда валидатор принял. Где была ошибка понять не могу.
Muerto22 уровень, Санкт-Петербург
9 марта, 19:08
Проверяйте построчно. Снизу выделяешь до второй строки Ctrl+x, Ctrl+z. Потом до третьей строки и т.д. Видно будет в какой строке ошибка. У меня в основном это пропадающие пробелы. Например for (StackTraceElement element : и подобные этому я всегда записываю как for (StackTraceElement element:.
Валерий15 уровень
3 марта, 05:50
Разжевал как только можно Видео
Igor Kotljar14 уровень
6 марта, 20:15
Спасибо. Но и до этого это ясно было, а как вызывать стеки и тд я не понял, след задачи тербуют этого
Даня15 уровень
28 февраля, 11:57
мне кажется или очень мало теории ?
virex25 уровень, Екатеринбург
28 февраля, 02:41
Для тех кто сразу не врубился: когда мы вызываем метод, внутри другого метода - java запоминает текущий метод в память - стек (произносится как "стЭк"). Чем "глубже" вызовы - тем больше записывается в стек информации. А когда происходит ошибка внутри какого-нибудь метода типа method3(), то java выводит сообщение в виде списка - стек-трейс:
Exception in thread "main" java.lang.NullPointerException //<-имя ошибки (исключения)
	at com.javarush.test.Solution.method3(Solution.java:98) <-место где произошло исключение
	at com.javarush.test.Solution.method2(Solution.java:92)
	at com.javarush.test.Solution.method1(Solution.java:87)
	at com.javarush.test.Solution.main(Solution.java:69)
Глядя на стек-трейс, можно сразу понять всю цепочку вызовов, и определить место вплоть до номера строки где произошла ошибка (!). В данном случае ошибка была в методе method3, в строке 98. Переходим на эту строку и видим:
int a[]=null;
a[1]=1;
Тут я намеренно обратился к ячейке массива который еще не создан. Поэтому ошибка NullPointerException .
NewBuy19 уровень, Санкт-Петербург
23 января, 13:09
А оказалось не так и сложно :)
NewBuy19 уровень, Санкт-Петербург
22 января, 19:17
Увидел тему, испугался, пошел спать.
Alexey28 уровень, Минск
31 января, 20:53
аналогично))) надо идти спать, а то голова пухнет