快速访问来电者信息 [英] Accessing caller information quickly

查看:87
本文介绍了快速访问来电者信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究Aspectj方面,该方面需要知道从何处调用它.目前,我正在使用

I'm working on an aspectj aspect which needs to know where it's invoked from. At the moment I'm using

new Throwable().getStackTrace();

要访问此信息,但每个方面都需要花费数百微秒的时间才能运行.

to access this information but each aspect is taking several hundred microseconds to run.

我看过SecurityManager,但这似乎只能让我得到类名.

I've looked at the SecurityManager but that only seems to be able to get me the class name.

我还错过了其他选择吗?

Are there any other alternatives I've missed?

更新

我对@apangin答案的评论中提到的JMH基准测试结果:

JMH Benchmark results referred to in my comment on @apangin's answer:

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

测试在Dell XPS13 9343(i5-5200U @ 2.2GHz)的Windows 10,JDK 1.8.0_112下运行

Tests run under Windows 10, JDK 1.8.0_112 on a Dell XPS13 9343 (i5-5200U @ 2.2GHz)

推荐答案

不幸的是,Throwable.getStackTrace()似乎是在纯Java 8中获取调用者框架的唯一可行选择.

Unfortunately, Throwable.getStackTrace() seems to be the only viable option to get the caller frame in pure Java 8.

但是,有一个特定于JDK的技巧只能访问一个选定的堆栈帧.
它使用非标准的sun.misc.SharedSecrets API.

However, there is a JDK-specific trick to access just one selected stack frame.
It uses non-standard sun.misc.SharedSecrets API.

public static StackTraceElement getCaller() {
    Exception e = new Exception();
    return sun.misc.SharedSecrets.getJavaLangAccess().getStackTraceElement(e, 2);
}

这里2是所需帧的索引.

Here 2 is the index of the required frame.

直到最新的JDK 8都可以正常工作,但是在JDK 9中将无法访问私有API.一个好消息是Java 9将具有新的标准

This works fine until the latest JDK 8, but private API will not be accessible in JDK 9. A good news is that Java 9 will have new standard Stack-Walking API. Here is how to do the same in Java 9.

public static StackWalker.StackFrame getCaller() {
    return StackWalker.getInstance(Collections.emptySet(), 3)
            .walk(s -> s.skip(2).findFirst())
            .orElse(null);
}

The alternative option, that works well for both older and newer versions of Java, is JVMTI GetStackTrace function. It requires linking native code though.

这篇关于快速访问来电者信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆