Felix
Felix

Reputation: 6104

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?

Upvotes: 5

Views: 2151

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44032

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.Argument(0) String query,
          @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.

Upvotes: 7

Related Questions