Introduction to ByteBuddy

This article is an excerpt from the ebook titled “Java Interceptor Development with ByteBuddy: Fundamental ”. The excerpt is the chapter one of the ebook.

Table of Content
Chapter 2: On Method Enter Advice

ByteBuddy is an open source Java based library for Java bytecode generation and manipulation. ByteBuddy is licensed under Apache License Version 2.0, and is freely available on Github. This book uses the term instrumentation to describe the bytecode generation, manipulation, and interception. This book provides example codes that applies ByteBuddy capability to intercept, add, modify and delete existing functionality of one or more Java classes by modifying their bytecode. With ByteBuddy, the instrumentation process can occur during maven build time, or application runtime.

Modern applications tend to be complex in nature because the application needs to fulfill different type of requirements, for example, functional requirement and non-functional requirement. These applications contains multiple modules with each of them has their own functional code. Because of the non-functional requirements, the functional code is surrounded by non-functional code, for example, security processing, logging, performance monitoring, resource usage tracing for pay-per-use billing, DevOps related processing, and others.

public double calculatePrice(){
double discount = getDiscount();
return this.price + this.deliveryCharge - discount;
}

calculatePrice method without non-functional code

@Secure(authority=”normalUser, premiumUser”)
public double calculatePrice(){
long startTime=System.currentMilliseconds();
logger.info("Calculate price start");

double discount = getDiscount();
double price = this.price + this.deliveryCharge - discount
logger.info(“Method end”);
perfLogger.info("Calculate price execution time:"+
(System.currentMillioseconds()-startTime));
return price;
}

calculatePrice method with non-functional code

The complexity increases when the non-functional code spans across
multiple methods in the application, which causes tight coupling
between functional code and non-functional code. The repeatedly use
of non-functional code across methods of different classes impose
copy-paste coding, which causes the code maintenance burden.

Separating Functional Code and Non-Functional Code

To remove the complexity, the application development team can separate the non-functional code from the application code, returns the method to its original form with pure functional code only. All the non-functional code will be re-factored into advice code. The application development team then utilizes the bytecode instrumentation capability of ByteBuddy to produce the instrumented code.

ByteBuddy adds the advice code to the functional code during maven build time or application runtime, and produces the instrumented code that contains the functional and non-functional code. The development team can configure the instrumentation programmatically using ByteBuddy.

ByteBuddy only changes the Java bytecode (Java class file), not the Java source code.

The benefits of using ByteBuddy:
• ByteBuddy automates the coding via bytecode instrumentation.
• ByteBuddy increases code reusability because all the non-functional code can be created in one advice code Java file, and then reuses many times in different method of different Java classes.
• Modify bytecode without re-compilation of entire application
• Modify bytecode without the need of restart of application server.

ByteBuddy uses these strategies to intercept the Java bytecode:
1. On Method Enter
2. On Method Exit
3. Around Advice

In this book, all the example codes is integrated into maven build process, therefore the interception and code generation are created during maven build time, not during the application runtime. There is only one chapter that will show on how to create interceptor during application runtime. However, the instrumentation used in maven build time are also applicable to instrumentation at application runtime.

ByteBuddy supports instrumentation that can inspect and modify existing Java bytecode. These techniques will be explained in this book:
1. Add new constructor, method and instance variable
2. Remove existing constructor, method and instance variable
3. Modify the value of instance variable.
4. Modify the value of method parameter.
5. Inspect the existing Java class structure, constructor signature,
method signature, and instance variable.
6. Generate new generic Java class, constructor, method, and instance
variable (upper bound, lower bound, multiple bound, wildcard, parameterized type, method type argument)
7. Add and remove annotation that is annotated on Java class, constructor,
method, instance variable, and parameter
8. Add and modify Java inner class (add first and second level inner
class, intercepting inner class and anonymous class).
9. Generate new Java class, Java interface, enum, annotation, and
abstract class.
10. Generate simple method and lambda expression.
11. Sharing data between advice codes.
12. Introduction to Java agent development with Java Instrumentation
API and ByteBuddy, which can intercept JDK core class. (one chapter only)

This book provides example Java code for implementing the advice code and ByteBuddy plugin for bytecode instrumentation. Most of the example code in each chapter uses maven build process to create the instrumented code. There is one chapter that uses ByteBuddy with Java instrumentation API to create the instrumented code at application runtime.

What is not covered in this book

ByteBuddy is an open source library that contains many functionalities.
However, this book does not cover these topics:
• How to instrument Record component
• How to instrument Java native method
• How to instrument lambda expression
• How to generate anonymous class
• How to instrument Java bytecode using bytecode instruction, for example, stack manipulation, and ByteCodeAppender

Java Decompiler

Java decompiler is required to inspect the instrumented code that is in Java class format. Java decompiler can convert the class file into Java source code. This is important for verifying the generated bytecode. This is the list of Java decompiler that is free to use:

Online tools:
https://jdec.app

Offline tools:
• JDecompiler

Development Environment

IDE: SpringToolSuite4 version 4.8, any Java IDE is also applicable.
JDK: OpenJDK-11+28
ByteBuddy: version 1.10.16
Maven dependencies:

<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.16</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.10.16</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</artifactId>
<version>1.10.16</version>
</dependency>

Conclusion

This chapter explains:
• What is ByteBuddy
• Definition of advice code, functional code, and instrumented code
• How ByteBuddy helps in software design and coding
• The knowledge and technique that will be learn in this book
• Development environment used in this book

I am very interested in Java, web app and mobile app development. I enjoy doing R&D in Java during my spare time

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store