AnnotationInvocationHandler - null check for hashCode / equals / toString computation?

Rafael Winterhalter rafael.wth at
Mon Nov 17 14:02:58 UTC 2014

Hello again,
I looked a little closer at the implementation of the
AnnotationInvocationHandler and I want to extend my question beyond the
equals method:

When I define an annotation

@Foo{ String value() }

and instantiate two such annotations as

class First {}


class Second {}

these annotations for First and Second have identical return values for
both their toString and hashCode methods and they are equal to one another.
If I do however change the annotation propery's type to for example int
without recompiling the classes that declare the two annotation instances,
I get different hash codes for both annotations and the toString method
prints something like

@Foo(value="sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy at 1540e19d

where the proxy is of course of different object identity for both
annotations. The hash code of the annotation is dependent on the hash code
of this very same exception proxy instance. Obviously, this is difficult to
reproduce for my third-party annotation invocation handler.

As far as it is my understanding, the exceptions related to annotations
(except the ClassNotFoundException) are triggered lazily on requesting a
property in order to allow the usage of an annotation value even if one of
its properties is "broken" as long as this property is not used within an
annotation. The reasoning for this distinction lies on the assumption that
annotations are rather meta data instead of an integral part of the
program. I argue that this implies that that the annotations for First and
Second should be equal. For example, I observed the use of annotations as
keys in maps where one implicitly relies on the functioning for the equals
and the hashCode methods. If I did not use the Foo::value property
directly, I would never encounter an exception but I would miss values that
were looked up in this very same map due to the hash code misses.

On a side note, the AnnotationTypeMismatchExceptionProxy promises to be
serializable but has a non-volatile field referencing a Method instance.
Would this not cause a serialization error?

Thanks for the information and best regards, Rafael

2014-11-17 10:54 GMT+01:00 Aleksey Shipilev <aleksey.shipilev at>:

> On 11/17/2014 12:52 PM, Aleksey Shipilev wrote:
> > Like Rafael, I wonder if we can/should throw the
> > IncompleteAnnotationException when accessing the annotation member
> > implicitly with equals(), not with the named accessor.
> This should be "*as well as explicitly* with the named accessor".
> -Aleksey.

More information about the core-libs-dev mailing list