Indivon Indivon - 1 year ago 80
Java Question

Bytebuddy: get method in intercepted fixedvalue

We're using bytebuddy to replace different annotated methods, e.g. like these:

public class Example{

public String foo(){
return "hello";
public String bar(){
return "world";

At the moment, we use a MethodDelegation:

new ByteBuddy().subclass(Example.class)

and the
has following:

public String interceptString(@Origin Method method) {
// fetch current value from DB
return db.fetchString(method);

As you can see, we need some information from the original method to fetch the right data from the database. This is working, but:

We only need the value from the database once (when the application starts). Afterwards, the value is not really dynamic. Due to performance reasons, we want to change the MethodDelegation into a FixedValue, so that there is only one call to the DB for each method/settting and all subsequent calls will use the "cached" fixed value.

Normally, we would use something like



private Object getValue(){
Method method = ???
return db.fetchString(method);

Since we need the method to resolve and fetch the data from the DB, this is missing. So, finally the question is:

Is there a possibility to pass the intercepted method the fixed-value or what could be a better option here?

k5_ k5_
Answer Source

One way to solve your problem would be to add a cache to your class. Basically add a field that stores the values and retrieves them from database on the first access.

Example code that should come close to what you want.

// Wrapper arround ConcurrentHashMap for the cached values
// An instance of that class will be a field in the subclass of Example
public static class ConfigCache {
    private Map<String, Object> values = new ConcurrentHashMap<>();

    public Object computeIfAbsent(String key, Function<String, Object> mappingFunction){
        return values.computeIfAbsent(key, mappingFunction);

public static void main(String[] args) throws Exception {
    Class<? extends Example> clazz = new ByteBuddy().subclass(Example.class)
             // Add a field to the class
            .defineField(CONFIG_CACHE, ConfigCache.class, Visibility.PUBLIC, FieldManifestation.FINAL)
            // Add a constructor that initializes the field
            .defineConstructor(Modifier.PUBLIC).withParameter(ConfigCache.class).intercept(new FieldAssignConstructor())
            .intercept( //
            .load(ByteBuddyEnhancer.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION).getLoaded();

    Example example = clazz.getConstructor(ConfigCache.class).newInstance(new ConfigCache());

// Use @FieldValue to access fields of a class  
public static Object intercept(@Origin Method method, @FieldValue(CONFIG_CACHE) ConfigCache cache){
    return cache.computeIfAbsent(method.getName(), key -> {
        // Do whatever you want here
        System.out.println("Computing for " + key);
        return null;

private static final String CONFIG_CACHE = "configCache";

Constructor implementation:

private static final class FieldAssignConstructor implements Implementation {
    public InstrumentedType prepare(InstrumentedType instrumentedType) {
        return instrumentedType;

    public ByteCodeAppender appender(Target implementationTarget) {
        return new ByteCodeAppender() {

            public Size apply(MethodVisitor methodVisitor, Context instrumentationContext,
                    MethodDescription instrumentedMethod) {

                StackManipulation.Size size = new StackManipulation.Compound(
                        MethodInvocation.invoke(new TypeDescription.ForLoadedType(Example.class)
                        MethodVariableAccess.REFERENCE.loadFrom(0), //
                        MethodVariableAccess.REFERENCE.loadFrom(1), //
                        MethodReturn.VOID).apply(methodVisitor, instrumentationContext);
                return new Size(size.getMaximalSize(), instrumentedMethod.getStackSize());
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download