【问题标题】:Why does fetching results using "new Throwable().getStackTrace()[1].getMethodName()" termed as expensive?为什么使用“new Throwable().getStackTrace()[1].getMethodName()”获取结果被称为昂贵?
【发布时间】:2020-04-27 04:01:30
【问题描述】:

我正在使用

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

它被一些开发人员称为昂贵。这种方法在什么方面是昂贵的?我们应该使用它吗?如果是,那么应该注意什么?

在我的用例中,非常需要找到调用方法名称。

大约有 50 个作业,因此这将在 Java8 中的独立程序中在 32 GB ram centos 上执行大约 100 次。

【问题讨论】:

  • 我相信堆栈跟踪的构建通常被认为是昂贵的部分。
  • @user2478398:但没有其他方法可以做到这一点。 32 GB 的内存和每天近 50-100 次点击要多少钱?
  • 每天50-100次点击基本没什么,不用担心性能。
  • 如果您必须每分钟执行数百次,那么您可能会遇到问题。
  • “在我的用例中,非常需要找到调用方法名称。”在我看来,这是一个破碎的设计。整个 Java SE 库中的任何方法都不会根据调用者来改变其行为。

标签: java stack-trace throwable


【解决方案1】:

您可以获取方法名称statically,而无需创建额外的Throwable对象

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

感谢@RiteshPuj

注意getStackTrace internally 仍然创建对象(ExceptionThread[]

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

对于 Java 9+,请使用 StackWalker(感谢 @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());
                   });
    }

【讨论】:

  • 谢谢。然后在我的情况下,它将是 Thread.currentThread().getStackTrace()[2].getMethodName() 因为我需要调用方法。但我的问题是为什么它被认为是昂贵的,并且在我的用例中大约有 50 个工作,所以这将在独立程序中每天在 32 gb ram centos 上执行大约 100 次。这有关系吗
  • 注意,这比创建Exception 之前已知。由于Thread 对象不知道调用者是否在同一个Thread 上,因此可以创建安全点。我不知道在 @fatherazrael 使用的任何 java 版本中是否仍然如此。
  • 如果您使用的是 java 9(或更高版本),则添加了堆栈遍历 API,这将允许更有效地定位此信息。跨度>
  • 我不明白这是如何“不创建对象”——它正在创建堆栈跟踪。
  • @JonSkeet true,更新为不创建 Throwable 对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 2011-06-18
  • 1970-01-01
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多