Я пытаюсь построить дерево вызовов в своем java-агенте с библиотекой byte buddy. Чтобы добавить элементы в дерево, я хочу использовать делегирование метода. Однако, чтобы убедиться, кто является родителем любого листа, мне нужно знать, кто вызвал метод.
Я не хочу использовать:
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
sun.reflect.Reflection#getCallerClass(int)
не просто устарел — он никогда не был частью официального API. Начиная с Java 9, официальным способом являетсяStackWalker.getCallerClass()
. - person Holger   schedule 08.01.2019StackWalker
, когда вы находитесь в Java 9 JRE, и вернитесь к устаревшему методу в более старых JRE. Официального способа для старых сред не существует, и устаревший метод не исчезнет в этих средах. - person Holger   schedule 08.01.2019Reflection.getCallerClass
не существует. Вы не можете найти вызывающий класс методаmain
, потому что методmain
не имеет вызывающего класса. Это также приведет к ошибке при попытке использоватьStackWalker.getCallerClass()
в методеmain
. - person Holger   schedule 10.01.2019