这就是我想要实现的目标:如果有一个a()
调用method的方法b()
,我想知道谁调用了method b()
。
public void a(){
b();//but it is not necessarily in the same class
}
public void b(){
String method = getCallerMethod();//returns 'a'
}
现在,可以使用StackWalker
API 在Java 9+中有效地实现这一目标。在Java 8中,我可以使用Thread.currentThread().getStackTrace()
或new Exception().getStackTrace()
,但是这两种方法都非常慢。我不需要整个堆栈跟踪,只需要堆栈跟踪中的前一帧,而只需要该帧中方法的名称(可能还需要类名)。
有没有办法在Java 8中有效地实现这一目标?
在JDK 8中,有一个内部未公开的API,它提供对单个堆栈跟踪元素的访问,而无需解码完整的堆栈跟踪:
SharedSecrets.getJavaLangAccess().getStackTraceDepth(e)
SharedSecrets.getJavaLangAccess().getStackTraceElement(e, index)
它有助于避免解码堆栈跟踪的巨额成本,但仍需要收集整个跟踪。有关详细信息,请参见此答案。
更快的方法是JVM TI GetStackTrace函数。其start_depth
和max_frame_count
参数仅允许获取堆栈跟踪的选定部分。
这种方法的缺点是它需要一个本机库。
我有一个使用它可以满足您所需的示例GetStackTrace
:StackFrame.getLocation(depth)
方法在给定深度仅返回一个堆栈帧。
如果只需要调用者类(没有确切的方法),则快速,标准和可移植的解决方案是
MethodHandles.lookup().lookupClass()
最后,如果仅需要调用者方法,则另一种解决方案是使用字节码检测找到所有invoke*
调用该方法的字节码a
,然后将其重写为invoke方法a_with_caller(String callerMethod)
,其中callerMethod
parameter是从检测的方法派生的检测时间常数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句