Эффективно получить абонента в MethodDelegation байтового приятеля - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь построить дерево вызовов в моем агенте 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 мс - слишком много, если у меня тысячи звонков).

Есть ли способ эффективно вызывать абонента в этот момент (может быть, уловки приятеля с байтами)?

P.S. Мой агент:

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: Java 8

1 Ответ

0 голосов
/ 09 января 2019

Инструментарий байтового кода позволяет вам генерировать код, который вы также можете написать самостоятельно. Для вашего случая вам нужно создать довольно навязчивую аппаратуру, которую я бы не рекомендовал:

  1. Инструмент вашего целевого метода для принятия нового параметра типа Class.
  2. Попросите каждого вызывающего абонента указать свой тип в качестве дополнительного аргумента.

Лучшее решение, конечно, то, что предложил Хольгер в комментариях. Используйте StackWalker и, если не доступно, вернитесь к sun.reflect.Reflection (который присутствует во всех JVM, о которых я знаю).

...