Field.getAnnotation is dead slow

C

charlesfr.rey

Anybody experienced this ?

It's not noticeable if you don't call getAnnotation often, but if
somehow you need to do this hundreds or thousands of times, there's a
good chance you'll notice it.

I had to implement my own Annotation cache (data structure: Map<Field,
Map<Class<?>, Annotation>>() ), but what I don't understand is that it
should already cache the info, looking into the JDK 5 source, in
Field.java, we have:

public <T extends Annotation> T getAnnotation(Class<T>
annotationClass) {
...
return (T) declaredAnnotations().get(annotationClass);
}

private transient Map<Class, Annotation> declaredAnnotations;

private synchronized Map<Class, Annotation> declaredAnnotations() {
if (declaredAnnotations == null) {
declaredAnnotations = ... parse annotations ...
}
return declaredAnnotations;
}

So, it should cache the annotations, but experience shows that it
doesn't.

Now, what's possible is that the JVM 5 that I have was not built from
the source code above ... ? Or am I missing something in the code ?

Using my own annotation cache (for Fields), performance is 20-25x
faster.
 
M

Mark Space

Using my own annotation cache (for Fields), performance is 20-25x
faster.

Every piece of documentation I've read on reflection (in Java) says that
reflection is slow, and advises not to use reflection if you can
possibly help it.

I didn't look at your code carefully but I can just about guarantee that
Java doesn't store annotations in a hash map. They're stored in the
..class files and have to be parsed, each time you look them up.

Also, consider a ConcurrentHashMap instead of a synchronized method. If
there's any significant concurrency in your program, the concurrent
version will likely be faster.
 
C

charlesfr.rey

I didn't look at your code carefully but I can just about guarantee that
Java doesn't store annotations in a hash map.  They're stored in the
.class files and have to be parsed, each time you look them up.

The code that I expose in my original post is taken from the source of
Java's Field class. My question is precisely about why this code does
a worse job at caching the annotations than a custom application-side
code.

Thanks for the answer anyway.

NB: JDK 5 source can be obtained through http://java.sun.com/j2se/jrl_download.html
(JDK 6 source for Field.java is similar than version 5, for the part
that I care about)
 
M

Mark Space

The code that I expose in my original post is taken from the source of
Java's Field class. My question is precisely about why this code does
a worse job at caching the annotations than a custom application-side
code.


Hmm, then I don't know. I'm very surprised to see that there's some kind
of caching at all on the Java API side. I'd have to trace out the code
and see what's actually being exectued.

I'd also be concerned about the Map retaining references to the class
objects after the class objects were no longer used. Seems like this
could potentially be a memory leak.
 
M

Mike Schilling

Mark said:
Hmm, then I don't know. I'm very surprised to see that there's some
kind of caching at all on the Java API side. I'd have to trace out
the code and see what's actually being exectued.

I'd also be concerned about the Map retaining references to the
class
objects after the class objects were no longer used. Seems like
this
could potentially be a memory leak.

Class object are kept in memory by the Classloader that loaded them.
So long as the class that keeps the map is loaded by the same
Classloader, no new memory leaks are introduced.
 
S

Stefan Rybacki

Anybody experienced this ?

...
Now, what's possible is that the JVM 5 that I have was not built from
the source code above ... ? Or am I missing something in the code ?

Using my own annotation cache (for Fields), performance is 20-25x
faster.

As far as I can see is that the Map you are referring to is not used globally
but locally for each Field instance. Which in return means ich generated
instance of Field has its own Map and is not aware of any other Map it could use
for caching purposes. An my guess is your cache Map actually works globally and
therefore must be alot faster.

Stefan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top