byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

Allow matching annotations by name without locating annotation bytecode

Open laurit opened this issue 3 years ago • 8 comments

Running TypePoolDefaultLazyAnnotationListTest comment out all tests besides testAnnotationIsPresent in AbstractAnnotationListTest. Add breakpoint to https://github.com/raphw/byte-buddy/blob/fbd78e1868c53b0c73b9528f821465bb3173794c/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/ClassFileLocator.java#L453 The breakpoint will hit 3 times for

net.bytebuddy.description.annotation.AbstractAnnotationListTest$Holder
net.bytebuddy.description.annotation.AbstractAnnotationListTest$Foo
net.bytebuddy.description.annotation.AbstractAnnotationListTest$Bar

Where Holder is the tested class and Foo and Bar are annotations on that class. It would be nice if it would be possible to do the match without locating Foo and Bar.

laurit avatar Apr 04 '22 17:04 laurit

This is tricky, the annotation contract dictates that annotations with missing types are not to be rendered. So to speak, if

net.bytebuddy.description.annotation.AbstractAnnotationListTest$Foo
net.bytebuddy.description.annotation.AbstractAnnotationListTest$Bar

cannot be located, there will not be an error but the annotations would not be there. This is why the types need to be looked up.

raphw avatar Apr 04 '22 18:04 raphw

From the api perspective it definitely makes sense to mimic what java annotation apis do and not return annotations with missing type. Though locating the bytes for the annotation class still has a non-zero cost. It would be nice if it would be possible to skip it without having to resorting to reflection to read annotationTokens from LazyTypeDescription.

laurit avatar Apr 06 '22 17:04 laurit

If you wanted to avoid the lookup, you can create a custom TypePool where you return the annotation type without looking it up from disk. Would that be a solution? Type pools can be arranged in a hierarchy so that you can lay your own pool underneath.

raphw avatar Apr 07 '22 07:04 raphw

I'm already using a custom TypePool so that is fine. How do I know that it is currently looking for an annotation?

laurit avatar Apr 07 '22 08:04 laurit

That's impossible, you would need to register the names. You can however do so by maintaining a set of names that are looked up?

The look up is triggered after the check so it would be delayed until you populated the set with the name.

raphw avatar Apr 07 '22 09:04 raphw

Alternatively, you could extend the type pool and ovverride the methods for reading annotations. The types are protected to type pool instances.

raphw avatar Apr 07 '22 09:04 raphw

Alternatively, you could extend the type pool and ovverride the methods for reading annotations. The types are protected to type pool instances.

what do you mean by methods reading annotations, getDeclaredAnnotations in MethodDescription?

That's impossible, you would need to register the names. You can however do so by maintaining a set of names that are looked up?

You mean that I'd keep a set of annotation type names and based on that return a different result from doDescribe. How do I fill that list, how would I know which annotations current type uses?

laurit avatar Apr 07 '22 11:04 laurit

Yes, you would have something like:

Set<String> annotations = new HashSet<>();
TypePool typePool = makePoolWithAssumedAnnotations(annotations);
annotations.add("my.Annotation");
assert typePool.describe("myType").resolve()getDeclaredAnnotations().filter(named("my.Annotation").size() == 1;

The pool would simply return a mocked up type description for an annotation type in the set if found.

raphw avatar Apr 07 '22 12:04 raphw