raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.23k stars 804 forks source link

`MemberAttributeExtension.ForField().on(…)` does not consider previously added annotations #1572

Closed odrotbohm closed 6 days ago

odrotbohm commented 9 months ago

Assume I have some code that adds an annotation to a field using:

new MemberAttributeExtension.ForField()
  .annotate(…);

and a second declaration (in another ByteBuddy plugin) that would attempt the same, but guards against the presence of the potentially previously added annotation:

new MemberAttributeExtension.ForField()
  .annotate(…)
  .on(…) // Receiving a filter for the annotation to be added

The condition handed into ….on(…) seems to only consider the annotations originally present on the type. I essentially need to write code that adds the annotation once as the individual invocations to add it don't know about each other. Alternatively, I wonder if the addition of an annotation could be deduplicated for identical AnnotationDeclarations as otherwise invalid annotation declarations are produced.

raphw commented 9 months ago

Unfortunately, the internal model is not currently strong enough to capture "on the fly changes" made by ASM visitors. Your best option right now would be to add a custom visitor that strips annotations by a given criteria and then write your own annotation after visiting everything that was added previously.

In order to avoid this, you can transform a type, write it to a byte array and then read it and reprocess it, but that is rather costly.

odrotbohm commented 9 months ago

I seem to run into this problem even with a single plugin declaring the annotation within Eclipse. I wonder whether this is related to m2e likely keeping the build plugin instance around. In that case, I think the class files are read once into TypeDescriptors, transformation logic is applied and the class files rewritten. A subsequent invocation of the plugin (the same instance) would then not re-read the TypeDescriptors, would it? Thus, the matching logic would still not see the guards and perform the annotation addition a second time?

Is there a way to tweak the ClassFileLocator so that it re-initializes for all invocations of the plugin instance?

raphw commented 9 months ago

This might be the cache that is used? Can you try to use a PoolStrategy that uses a no-op cache?