raphw/byte-buddy

Setting value in constructor aliases collections

jimshowalter opened this issue · 5 comments

In #1638 I thought we had a solution to defining a constructor that initializes a field to a value:

.defineConstructor(Visibility.PUBLIC)
.intercept(
    MethodCall.invoke(getConstructor(entityClass))
        .onSuper()
        .andThen(
            FieldAccessor.ofField(MODIFIED_FIELDS_TRACKER_FIELD_NAME)
                .setsValue(new HashSet<String>())))

But that turns out to put the same collection in all instances of the class, instead of creating a new hash set per instance:

Screenshot 2024-05-13 at 8 07 26 PM

How can I create a new hash set each time?

try to use

.intercept(MethodCall.invoke(getConstructor(entityClass))
    .onSuper()                   
    .andThen(MethodCall.construct(HashSet.class.getConstructor())
        .setsField(named(MODIFIED_FIELDS_TRACKER_FIELD_NAME))
    )
);

That seems to have worked!

The only thing now is the decompiled constructor isn't calling super. Is that okay?

import lombok.Data;

@Data
public class Foo {
  private String bar;
  private int ignoreMe;
}

public class Foo$Setter$Tracking$ByteBuddy$Subclass extends Foo {
    private final Set<String> _modified$Fields$Tracker = new HashSet();

    public Foo$Setter$Tracking$ByteBuddy$Subclass() {
    }

    static {
        cachedValue$SAlkJfUp$ojd8qn2 = Foo.class.getMethod("setIgnoreMe", Integer.TYPE);
        cachedValue$SAlkJfUp$jj42cs3 = Foo.class.getMethod("setBar", String.class);
    }
}

(Same behavior if lombok is replaced with manually-declared methods.)

You could not load the class if it did not call super, I assume it's simply not printed as this is implicit.

That's my assumption too. It's just a bit disconcerting that the .class bytecode doesn't render showing it. Could also be an IntelliJ limitation. Was going to try some command-line decompiler but jad isn't maintained, fernflower requires cloning their mirror, etc. Javap doesn't appear to be able to reconstruct pretty-printed source.

What does javap show?