Search code examples
javainstrumentationjavaagentsbyte-buddy

Instrument all implementations of a set of interfaces with ByteBuddy


Background: I want to instrument all implementations of a set of interfaces (within the same package) with a LogInterceptor (just logging that the method was called). Therefore I wrote a javaagent with byte-buddy. In general that is working fine, but I'm struggling with finding all implementations of a set of interfaces.

Assume we have a set of Java interfaces in a package my.company.api, then I tried it the following way:

public static void premain(String arguments, Instrumentation instrumentation) {
    new AgentBuilder.Default()
        .ignore(ElementMatchers.isInterface())
        .ignore(ElementMatchers.isEnum())
        .type(ElementMatchers.nameMatches("my\\.company\\.api\\..*"))
        .transform(new AgentBuilder.Transformer() {
            @Override
            public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classloader) {
                return builder
                        .method(ElementMatchers.isPublic())
                        .intercept(MethodDelegation.to(LogInterceptor.class));
        }
    }).installOn(instrumentation);
}

I am quite new with byte-buddy, maybe someone can give me a hint what I am doing wrong.


Solution

  • First of all, you are not chaining the ignore matchers correctly; it should be:

    .ignore(isInterface().or(isEnum()))
    

    As for matching the interfaces, you can try the hasSuperType matcher. If you try to match interfaces of a given package, you might try:

    hasSuperType(nameStartsWith("my.company.api.").and(isInterface()))
    

    Using a prefix matcher is much more efficient compared to a regex.