有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在byte buddy的MethodDelegation中高效地获取调用方

我正试图在我的java代理中使用byte buddy库构建一个调用树。要将元素添加到树中,我想使用方法委派。但是,为了确定谁是任何叶的父对象,我需要知道是谁调用了该方法

我不想使用:

sun.reflect.Reflection#getCallerClass(int)

因为它已被弃用,在Java8+中不可用。 此外,我尝试:

public class ThreadUtil {

public static StackTraceElement getCaller() {
    Instant now = Instant.now();
    StackTraceElement ste = Thread.currentThread().getStackTrace()[3];
    String callerClass = ste.getClassName();
    String callerMethod = ste.getMethodName();
    Instant now2= Instant.now();
    System.out.println(Duration.between(now, now2));
    return ste;
}

}

但是,它的速度非常慢(~1毫秒——如果我有数千个电话,那就太慢了)

在这一点上,有没有一种方法可以让来电者高效地通话(可能是一些byte buddy的技巧)

附言。 我的代理人:

private static void instrument(String agentOps, Instrumentation inst) {
    System.out.println("Agent");
    new AgentBuilder.Default().with(new Eager())
            .ignore(ElementMatchers.nameContains("com.dvelopp.agenttest"))
            .type((ElementMatchers.any()))
            .transform((builder, typeDescription, classLoader, module) -> builder.method(ElementMatchers.any())
                    .intercept(MethodDelegation.to(Interceptor.class))).installOn(inst);
}

public static class Interceptor {

    @RuntimeType
    public static Object intercept(@SuperCall Callable<?> zuper, @Origin Method method,
                                   @AllArguments Object[] args, @This(optional = true) Object me) throws Exception {
        System.out.println("CURRENT: " + method.getDeclaringClass().getName());
        System.out.println("CALLER: " + ThreadUtil.getCaller().getClassName());
        return zuper.call();
    }

}

ENV:java8


共 (1) 个答案

  1. # 1 楼答案

    字节码检测只允许您生成也可以自己编写的代码。对于您的情况,您需要创建一个我不推荐的相当侵入性的工具:

    1. 向目标方法插入指令,以接受类型为Class的新参数
    2. 指示每个调用方将其类型作为附加参数提供

    更好的解决方案肯定是霍尔格在评论中提出的。使用StackWalker,如果不可用,则返回到sun.reflect.Reflection(我所知道的所有JVM中都有)