SoFunction
Updated on 2025-04-14

Technical Guide to Use ByteBuddy Dynamic Bytecode Operation Library in Java

1. Brief description

ByteBuddy is a powerful Java bytecode operation library that helps developers dynamically generate and modify classes at runtime without having to directly contact with complex ASM APIs. It is widely used in the fields of framework development, AOP (sectional programming), proxy generation, performance monitoring, etc.

2. Advantages of ByteBuddy

  • High-level abstraction: Compared to ASM that directly operates bytecode, ByteBuddy provides a more advanced and easy-to-use API, simplifying dynamic bytecode operations.
  • Strong flexibility: Supports complex bytecode generation and modification, suitable for a variety of scenarios.
  • No dependency: Rely on Java itself only, no external libraries are required.
  • Integrate with existing tools: Good compatibility, supports Java proxy mechanism, and can be seamlessly integrated with frameworks such as Spring and Hibernate.

3. Basic usage

3.1 Add dependencies

First, add ByteBuddy's Maven dependency to your project:

<!-- bytebuddy -->
<dependency>
    <groupId></groupId>
    <artifactId>byte-buddy</artifactId>
    <version>1.14.5</version>
</dependency>
<dependency>
    <groupId></groupId>
    <artifactId>byte-buddy-agent</artifactId>
    <version>1.14.5</version>
</dependency>

3.2 Create dynamic classes

The following example demonstrates how to create a class dynamically:

import ;
import ;
import ;

public class ByteBuddyExample {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        // Use ByteBuddy to generate a class dynamically        Class&lt;?&gt; dynamicClass = new ByteBuddy()
                .subclass() // Inherited from Object                .name("") // Set the class name                .method(named("toString")) // Override the toString method                .intercept(("Hello, ByteBuddy!")) // Return a fixed value                .make() // Create class definition                .load(()) // Load to the current class loader                .getLoaded();

        // Instantiate the dynamic class and call the toString method        Object instance = ();
        (()); // Output: Hello, ByteBuddy!    }
}

3.3 Modify existing classes

passAgentBuilder, ByteBuddy can modify existing classes at runtime. For example, modify the behavior of a method:

import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;

import static ;

public class ModifyClassExample {
    public static void main(String[] args) {
        Instrumentation install = ();// Install the agent for ByteBuddy
        ResettableClassFileTransformer sayHello = new ()
                .type(named("")) // Match the target class                .transform(new () {
                               @Override
                               public &lt;?&gt; transform(&lt;?&gt; builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, ProtectionDomain protectionDomain) {
                                   return (named("sayHello")) // Match the target method                                           .intercept(());
                               }
                           } // Add facet logic                ).installOnByteBuddyAgent();

        // Call the modified method        ExistingClass existingClass = new ExistingClass();
        (); // Output: Modified: Hello, World!    }

    public static class SayHelloAdvice {
        @
        public static void onEnter() {
            ("Modified: Hello, World!");
        }
    }
}

class ExistingClass {
    public void sayHello() {
        ("Hello, World!");
    }
}

3.4 Implement dynamic proxy

Here is an example of implementing dynamic proxy using ByteBuddy:

import ;
import ;

import ;
import ;

public class DynamicProxyExample {
    public static void main(String[] args) throws Exception {
        // Dynamically generate proxy classes        Class&lt;?&gt; proxyClass = new ByteBuddy()
                .subclass()
                .implement() // Implement the interface                .method(named("greet")) // Match interface method                .intercept((new GreetingHandler())) // Intercept method call                .make()
                .load(())
                .getLoaded();

        // Instantiate the proxy class and call the method        Greeting greeting = (Greeting) ().newInstance();
        (("ByteBuddy")); // Output: Hello, ByteBuddy!    }
}

public interface Greeting {
    String greet(String name);
}

public class GreetingHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return "Hello, " + args[0] + "!";
    }
}

4. Practical application scenarios

  • AOP (System-oriented Programming): Add logic before and after the method is executed, such as logging and performance monitoring.
  • Proxy class generation: Dynamically implement interfaces or classes for simulation, testing or interception.
  • Framework Development: Dynamically generate bytecodes such as Hibernate to optimize performance.
  • Bytecode enhancement: Enhance existing classes at runtime, such as security checks and behavior modifications.

5. Summary

ByteBuddy is a powerful and easy-to-use bytecode operation tool, providing Java developers with an efficient solution to manipulate bytecode. From the above example, we can see that whether it is dynamically generating classes, modifying existing classes, or implementing dynamic proxying, ByteBuddy provides great flexibility and convenience. If you need to operate classes dynamically in your project, you can try using ByteBuddy to simplify the development process.

The above is the detailed information of the technical guide for using the ByteBuddy dynamic bytecode operation library in Java. For more information about the use of the ByteBuddy library, please pay attention to my other related articles!