Good day. Help me understand the essence of StackTrace.

The study material explains

The java machine records all function calls. She has a special collection for this - the stack. When one function calls another, the Java machine pushes a new StackTraceElement into this stack. When the function ends, this item is removed from the stack. Thus, this stack always keeps up-to-date information about the current state of the “function call stack”

The following is an example.

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()); } } 

As a result of which we get

 getStackTrace method3 method2 method1 main 

If I understand everything correctly, then the design

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

works as follows:

 //Cоздаём переменную типа StackTraceElement[] StackTraceElement[] stackTraceElements //Присваеваем ей ссылку на текущий поток и заносим в массив специальные элементы StackTrace Thread.currentThread().getStackTrace() 

Question number 1: how in this array StackTraceElement[] all the information about the called methods, if it is said that after executing the method information from the stack is removed?

Question number 2: In one of the tasks asked to return the name of the method that calls it

  public static void main(String[] args) throws Exception { method1(); } public static String method1() { method2(); return Thread.currentThread().getStackTrace()[2].getMethodName(); } public static String method2() { method3(); return Thread.currentThread().getStackTrace()[2].getMethodName(); } public static String method3() { method4(); return Thread.currentThread().getStackTrace()[2].getMethodName(); } public static String method4() { method5(); return Thread.currentThread().getStackTrace()[2].getMethodName(); } public static String method5() { return Thread.currentThread().getStackTrace()[2].getMethodName(); } 

How does the design work

 return Thread.currentThread().getStackTrace()[2].getMethodName(); 

if we did not create a StackTraceElement[] . Does this mean that it is implicitly created by the JVM during program execution?

  • one
    if we did not create a StackTraceElement [] - it is never created on the user side at all, it is always provided by the JVM - etki
  • Clear. And what about the first question? - Roman DriveMind
  • one
    Well, strictly speaking, StackTraceElement is not a link to the stack, it is its presentation at a certain point in time, so there is no problem to “hold” it and release it in another place (everything will be a little different in the new API, which will be added in the next java, but this is a separate topic). But specifically in these examples, it is not held anywhere and is used exactly in those places that should be answered during the execution of the method . - etki

3 answers 3

Question number 1: how in this array StackTraceElement[] all the information about the called methods, if it is said that after executing the method information from the stack is removed?

You call the getStackTrace() method in method3() . At the time of the getStackTrace() call, the getStackTrace() method has not yet completed , therefore, the getStackTrace() method getStackTrace() return the entire call chain up to the getStackTrace() method call.

If, for example, you call getStackTrace() in the main(...) method after calling method1() , you will get the following output:

 getStackTrace main 

You do not see method1() and other methods here - the records of their calls have been deleted, because at the time of the getStackTrace() method method1() was completed .

Question number 2: In one of the tasks asked to return the name of the method that calls it

...

How does the design work

 return Thread.currentThread().getStackTrace()[2].getMethodName(); 

if we did not create a StackTraceElement []. Does this mean that it is implicitly created by the JVM during program execution?

Yes it means. The elements in the call stack are added by the JVM itself.

At the top of the stack is an entry about the call to the getStackTrace() method getStackTrace() , followed by an entry about the name of the method in which the getStackTrace() method was called getStackTrace() , in the getStackTrace()[i] element ( i>0 ) there is the name of the method that caused method that is in getStackTrace()[i-1] .

  • That's it. So if I just wrote 5 methods and didn't call them friend-in-friend, then the element in the array would be only two - getStackTrace and the name of the method in which it was called? - The novel DriveMind
  • one
    @ RomanDriveMind, Yes, that's right. - post_zeew
  • Thank you, now everything has become clear - Roman DriveMind

Just do not understand why you return [2] element. In your task you need to return the name of the method that calls it.

 public static String method5() { return Thread.currentThread().getStackTrace()**[2]**.getMethodName(); } 

In this case, it will be Thread.currentThread().getStackTrace().length current method 5. Stack length can be checked by calling the length method: Thread.currentThread().getStackTrace().length - the number of recorded methods in the Stack, in this case there will be 7 entries. The final element will be the getStacktrace() method getStacktrace() . We need to return the method that calls it, so i-1 (6) needs to be returned. As a result, we get:

 return Thread.currentThread().getStackTrace()[6].getMethodName(); 

For method 4 will be

 return Thread.currentThread().getStackTrace()[5].getMethodName(); 

But if you want to print the line number that called this method, then yes, return Thread.currentThread().getStackTrace()[2].getLineNumber() will return the line number of method 4, which called method 5.

    The answer above is a bit inaccurate. In the stack, always the method that called StackTrace will be on position [2].

    • 0 - getStackTrace

    • 1 - method name (your name)

    • 2 - name of the method who called [1]

    • 3 - name of the method who called [2]

    • 4 - etc

    Here we see the past, what happened before the current method was launched.

    • Explain, where is the inaccuracy? There is the same thing, only in other words. - 0xdb
    • @BeardedBeaver Your editing removes not only unnecessary, but also punctuation. The message is written in the "national language", but if you rule, you will also notice it in accordance with the norms of the Russian language. - 0xdb