1

I am using

new Throwable().getStackTrace()[1].getMethodName()

It is termed as expensive by some developers. In what way this method is expensive? Shall we use it and if yes then what caution should be taken?

In my use case, it is very much required to find calling method name.

There are around 50 jobs so this will get executed around 100 times on 32 gb ram centos in a standalone program in Java8.

fatherazrael
  • 5,511
  • 16
  • 71
  • 155
  • 1
    I believe the building of the stack trace is typically considered the expensive part. – BeUndead Jan 09 '20 at 14:11
  • @user2478398: But there is no other way to do that. How much expensive it is for 32 gb ram and nearly 50-100 hits per day? – fatherazrael Jan 09 '20 at 14:14
  • 6
    50-100 hits per day is basically nothing, don't worry about performance. – Joachim Sauer Jan 09 '20 at 14:22
  • Obtaining the stacktrace is expensive, as it needs a thread dump to do so. It is also one of the reasons why, for instance, java.util.logging is slow (it uses the same mechanism to obtain the caller). See http://java-performance.info/throwing-an-exception-in-java-is-very-slow/ as well. But slow doesn't mean it slows you down, it is slow in comparison to code that doesn't create an exception. – M. Deinum Jan 09 '20 at 14:24
  • @JoachimSauer: Thanks. I mean at what amount should i scare of per day? 400 - 500? – fatherazrael Jan 09 '20 at 14:25
  • 2
    If you had to do that many hundred times per minute, then you might run into problems. – Joachim Sauer Jan 09 '20 at 14:27
  • @JoachimSauer: Ok because in my case i have say 20 schedulers who and each calls this method two times at start and end of job. So if we use 50 schedulers and all run at single times and in one minute they do this. then it might cause problem. But again not in 100 or 200 but many 100s – fatherazrael Jan 09 '20 at 14:28
  • 1
    “In my use case, it is very much required to find calling method name.” That is a broken design, in my opinion. No method in the entire Java SE library changes its behavior based on who is calling it. – VGR Jan 09 '20 at 14:49
  • Can you add the use case for using it in runtime? – Ori Marko Jan 09 '20 at 14:56
  • @VGR: I agree that it's a bad design, but your second statement is not correct. Basically the entire permission system (as little-used as it is right now) depends on which code calls which code. There's even the `@CallerSensitive` annotation and JEP 176 to help with requirements like this. [`StackWalker.getCallerClass`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StackWalker.html#getCallerClass()) is an obvious counter-example. – Joachim Sauer Jan 10 '20 at 10:14

1 Answers1

1

You can get method name statically, without creating extra Throwable object

Thread.currentThread().getStackTrace()[1].getMethodName()

Thanks for @RiteshPuj

Notice getStackTrace internally still create object (Exception or Thread[])

   StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
...
} else {
   // Don't need JVM help for current thread
   return (new Exception()).getStackTrace();

For Java 9+ use StackWalker (Thanks for @StuartMarks)

public void methodB(){
        System.out.println("I am methodB");
        StackWalker.getInstance()
                   .walk(frames -> frames.skip(1).findFirst())
                   .ifPresent(frame -> {
                        System.out.println("I was called by a method named: " + frame.getMethodName());
                   });
    }
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • Thanks. Then In my case it will be Thread.currentThread().getStackTrace()[2].getMethodName() as i need calling method. But my question was why it is considered as expensive and in my use case There are around 50 jobs so this will get executed around 100 times on 32 gb ram centos daily in standalone program. Does this matter anyway – fatherazrael Jan 09 '20 at 14:20
  • 2
    Note, this has been known to previously be _slower_ than creating an `Exception`. Since the `Thread` object doesn't know if the caller is on the same `Thread`, and so safe-points can be created. I don't know if this is still the case in whatever java version @fatherazrael is using. – BeUndead Jan 09 '20 at 14:21
  • 1
    If you're using java 9 (or higher), then a stack walking API has been added, which will allow for _much_ more efficient locating of this information. – BeUndead Jan 09 '20 at 14:22
  • 1
    I don't see how this is "without creating an object" - it's creating a stack trace. – Jon Skeet Jan 09 '20 at 14:23
  • @JonSkeet true, updated to without creating `Throwable` object – Ori Marko Jan 09 '20 at 14:26
  • @user2478398 is correct. The [StackWalker](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/StackWalker.html) class lets you simply write `StackWalker.getInstance().getCallerClass()`. – VGR Jan 09 '20 at 15:13
  • @VGR OP has Java 8 and want the caller method – Ori Marko Jan 09 '20 at 15:28