代码之家  ›  专栏  ›  技术社区  ›  dvelopp

有效地让调用者进入byte buddy的methoddelegation

  •  1
  • dvelopp  · 技术社区  · 6 年前

    我试图用字节好友库在Java代理中构建一个调用树。要向树中添加元素,我要使用方法委托。但是,为了确保谁是任何叶的父级,我需要知道谁调用了该方法。

    我不想使用:

    sun.reflect.Reflection#getCallerClass(int)
    

    因为它在Java 8 +中是不可用的和不可用的。 我也尝试过:

    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毫秒-如果我有数千个电话,就太慢了)。

    在这一点上,有没有一种方法可以有效地让调用者(也许是一些字节伙伴的技巧)?

    附笔。 我的经纪人:

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

    爪哇8

    1 回复  |  直到 6 年前
        1
  •  1
  •   Rafael Winterhalter    6 年前

    字节代码插入只允许您生成也可以自己编写的代码。对于您的案例,您需要创建一个相当侵入性的工具,我不建议这样做:

    1. 检测目标方法以接受类型为的新参数 Class .
    2. 检测每个调用方以提供其类型作为附加参数。

    更好的解决办法当然是霍尔格在评论中提出的。使用 StackWalker 如果没有,回到 sun.reflect.Reflection (在我所知的所有JVM中都有)。