-
-
Notifications
You must be signed in to change notification settings - Fork 84
Description
First post here, so let me thank you for sharing Jackson with us all. It's a great library and a wonderful asset to the Java community. 👍
AnnotationBundleKey._equals uses == instead of .equals() to compare annotations. This approach does not work with method parameter annotations, which are not cached and not guaranteed to be the same. I was going to submit a PR using .equals(), but it looks like this behavior is intentional from a comment in the test. I'm not sure if this will break anything else but wanted to raise it to your attention.
This issue was discovered because AnnotationBundleKey is used by RestEasy as part of a key to a ConcurrentHashMap in ResteasyJackson2Provider. Because RestEasy used this class with parameter annotations, object equality was failing with the same hash code, leading to lock contention and performance issues. I've submitted a PR with RestEasy to fix the issue there but wanted you to be aware as well.
Here's a snippet which shows the issue.
import com.fasterxml.jackson.jaxrs.cfg.AnnotationBundleKey;
import javax.annotation.Nonnull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class AnnotationEqualitySnippet {
@Nonnull
public void annotatedMethod(@Nonnull String a) {}
public static void main(String[] args) throws Exception {
Method method = AnnotationEqualitySnippet.class.getMethod("annotatedMethod", String.class);
Annotation[] ann1 = method.getParameterAnnotations()[0];
Annotation[] ann2 = method.getParameterAnnotations()[0];
AnnotationBundleKey key1 = new AnnotationBundleKey(ann1, Object.class);
AnnotationBundleKey key2 = new AnnotationBundleKey(ann2, Object.class);
System.out.println(key1.equals(key2)); // outputs "false" ("true" expected)
}
}