Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to return from a method using @Advice.OnMethodEnter?

Using Byte Buddy's advice API, is it possible to return from the instrumented method without actually executing it?

One use case would be to implement a cache and to return the cached value, if present, instead of computing the value again.

@Advice.OnMethodEnter
public static Object returnCachedValue(@Advice.Argument(0) String query) {
    if (cache.containsKey(query)) {
        // should "abort" method call
        return cache.get(query);
    }
}

I know that this code sample above just creates a local variable which I can get in a @Advice.OnMethodExit method. But is there a way to abort the method call on an explicit return? If yes, is this also possible for void methods?

like image 919
Felix Avatar asked May 08 '18 15:05

Felix


1 Answers

No, this is not possible, a return value can only be set from exit advice. But it can be emulated by skipping the original method in case that a value already exists and by setting this value from the exit advice in case that the enter advice defines a value:

class MyAdvice {
  @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
  public static Object returnCachedValue(@Advice.Argument(0) String query) {
    if (cache.containsKey(query)) {
      return cache.get(query);
    } else {
      return null;
    }
  }

  @Advice.OnMethodExit
  public static void processCachedValue(
          @Advice.Return(readOnly = false, typing = DYNAMIC) Object returned,
          @Advice.Enter Object enter) {
    if (enter != null) {
      returned = enter;
    } else {
      cache.put(query, returned);
    }
  }
}

Of course, this does not work if the cached value is null. To avoid this, you could wrap the value in some instance to make sure that the enter value is never null. Doing so would also allow to use the above pattern to void methods.

This might look inconvenient to program but the idea of advice is that Byte Buddy can use the advice class as a template and inline the byte code without much work to avoid a runtime overhead.

like image 193
Rafael Winterhalter Avatar answered Sep 28 '22 06:09

Rafael Winterhalter