问题
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