JDK-8011940 : java.lang.Class.getAnnotations() always enters synchronized method
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 6u31
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2013-03-20
  • Updated: 2018-06-07
  • Resolved: 2013-09-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b110Fixed
Related Reports
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
springframework 3.1.2 makes heavily use of
java.lang.Class.getAnnotations() when instantiating Objects using loadTimeWeaving.
On our multicore-machines (24 cores) the heavily use causes a bottleneck because getAnnotations() internally uses a synchronized method that checks if the cache is filled or stale.
Looking at the sourcecode of java.lang.Class, without much internal knowledge, it looks like, that a kind of double-checked locking could avoid the entry of the synchronized method most of the time:
- put cached annotations in local variable
- check if variable is null or the caches need to be resettet because of class-redefinition, by looking at the two counters
- if everything ist fine return local variable
- else enter the synchronized block like now.

Probably initAnnotationsIfNecessary needs to be restructured for use with local variables to avoid concurrency-Effects during the Construction of the cached annotations-List.

Theoretically there could occur a class redefinition of the class between check and return of the value, but a concurrency-Problem like that could always occur while asking something about the class an before continuing another thread could alter the class.

The current code looks like it could give wrong data for annotations, if one thread clears/refills the cache during initAnnotationsIfnecessary(), while the other just finished initAnnotationsIfnecessary() and goes on with
return AnnotationParser.toArray(annotations)



JUSTIFICATION :
The enhancement is necessary because of bottleneck behaviour on multicore machines that often ask for annotations of the same class.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No synchronization while calling getAnnotations as long as the class is not redefined.
ACTUAL -
Every Call to getAnnotations is synchronized causing bottleneck behaviour.

---------- BEGIN SOURCE ----------
Executor-Pool with a lot of threads calling getAnnotations for some Class.
---------- END SOURCE ----------