Can a method call be instrumented with ByteBuddy instead of the called method?

雨燕双飞 提交于 2021-02-04 14:19:45

问题


I would like to replace some AspectJ code that protects calls to java.lang.System from some user code. java.lang.System cannot/should not be instrumented.

With AspectJ the solution is to instrument the calling code like the following example. The code that should be guarded will be instrumented while the code that is allowed is not.

@Around("call(public long java.lang.System.currentTimeMillis()) && within(io.someuserdomain..*) && !within(io.someotherdomain..*))
def aroundSystemcurrentTimeMillis(wrapped: ProceedingJoinPoint): Long = {
      throw new IllegalStateException("must not call System.currentTimeMillis in usercode")
}

Is there a way to do the same using ByteBuddy? So far I only found examples on how to instrument the callee instead of the caller.


回答1:


You can currently replace a method or field access by registering a MemberSubstitution but the capabilities are still limited compared to AspectJ. It is for example not possible to throw an exception as in your example code. You can however delegate to a method that would contain the code that throws the exception:

MemberSubstitution.relaxed()
  .method(named("currentTimeMillis"))
  .replaceWith(MyClass.class.getMethod("throwException"))
  .in(any());

The above substitution would replace any method call with a call to the following member:

public class MyClass {
  public static long throwException() {
    throw new IllegalStateException();
  }
}

The substitution would be applied to any method onto which the visitor is applied. You can register an AgentBuilder.Default to build a Java agent to do so or have a look into Byte Buddy's build plugins.



来源:https://stackoverflow.com/questions/57808499/can-a-method-call-be-instrumented-with-bytebuddy-instead-of-the-called-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!