我正在研究aspectj方面,它需要知道从哪里调用它。我现在用的是
new Throwable().getStackTrace();要访问这些信息,每个方面都需要几百微秒才能运行。
我看过SecurityManager,但这似乎只能给我一个类名。
还有其他我错过的选择吗?
更新
我在评论@apangin的答复时提到了JMH的基准结果:
Benchmark Mode Cnt Score Error Units
MyBenchmark.javalangaccess13i avgt 100 2025.865 ± 8.133 ns/op
MyBenchmark.javalangaccess2i avgt 100 2648.598 ± 24.369 ns/op
MyBenchmark.throwable1 avgt 100 12706.978 ± 84.651 ns/op基准代码:
@Benchmark
public StackTraceElement[] throwable1() {
return new Throwable().getStackTrace();
}
@SuppressWarnings("restriction")
@Benchmark
public static StackTraceElement javalangaccess2i() {
Exception e = new Exception();
return sun.misc.SharedSecrets.getJavaLangAccess().getStackTraceElement(e, 2);
}
@SuppressWarnings("restriction")
@Benchmark
public static StackTraceElement javalangaccess13i() {
Exception e = new Exception();
return sun.misc.SharedSecrets.getJavaLangAccess().getStackTraceElement(e, 13);
}测试运行在Windows10,JDK 1.8.0_112上的戴尔XPS13 9343 (i5-5200U @ 2.2GHz)
发布于 2016-10-25 21:24:41
不幸的是,Throwable.getStackTrace()似乎是在纯Java8中获得调用方框架的唯一可行选择。
但是,有一个特定于JDK的技巧,即只访问一个选定的堆栈框架。
它使用非标准的sun.misc.SharedSecrets API.
public static StackTraceElement getCaller() {
Exception e = new Exception();
return sun.misc.SharedSecrets.getJavaLangAccess().getStackTraceElement(e, 2);
}这里2是所需帧的索引。
这在最新的JDK 8之前运行良好,但是在JDK 9中不能访问私有API。好消息是Java9将有新的标准堆栈遍历API。下面是如何在Java 9中做同样的事情。
public static StackWalker.StackFrame getCaller() {
return StackWalker.getInstance(Collections.emptySet(), 3)
.walk(s -> s.skip(2).findFirst())
.orElse(null);
}替代选项是JVMTI GetStackTrace函数,它适用于较早版本和较新版本的Java。不过,它需要链接本地代码。
https://stackoverflow.com/questions/40246227
复制相似问题