Proxy.isProxyClass scalability

Peter Levart peter.levart at gmail.com
Thu Jan 24 13:49:56 UTC 2013


Hello,

Recently I stumbled upon the scalability problem of 
j.l.r.Proxy.isProxyClass(Class) method when trying to find-out why the 
equals() method of annotations is not scalable. The reason is that 
j.l.r.Proxy uses a single synchronized wrapper around WeakHashMap to 
keep track of proxy classes in order to implement isProxyClass method:

  244     /** set of all generated proxy classes, for isProxyClass implementation */
  245     private static Map<Class<?>, Void> proxyClasses =
  246         Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());


  631     public static boolean isProxyClass(Class<?> cl) {
  632         if (cl == null) {
  633             throw new NullPointerException();
  634         }
  635
  636         return proxyClasses.containsKey(cl);
  637     }


In the discussion on the cuncurrency-interest list:

* 
http://cs.oswego.edu/pipermail/concurrency-interest/2013-January/010642.html

...it was indicated that other places in JDK besides the annotation's 
equals() method suffer from this scalability bottleneck, mainly in the 
field of serialization, RMI and JMX.

With the help from this discussion, I prepared a possible fix which I'm 
proposing here:

http://dl.dropbox.com/u/101777488/jdk8-tl/isProxyClass/webrev.01/index.html

The fix drops usage of synchronized wrapper and WeakHashMap and replaces 
them with a ClassValue and a little ThreadLocal trick to initialize it. 
The ThreadLocal trick could be replaced with a simple static variable 
guarded by a synchronized block if desired.

I have some results from a micro-benchmark that exercises the 
annotation's equals method. The results were obtained on two different 
systems:

* https://raw.github.com/plevart/jdk8-tl/proxy/test/benchmark_results.txt

The benchmark sources:

* 
https://github.com/plevart/jdk8-tl/blob/proxy/test/src/test/AnnotationEqualsTest.java
* 
https://github.com/plevart/micro-bench/blob/master/src/si/pele/microbench/TestRunner.java

Thanks to Aleksey Shipilev for showing me the obvious pitfalls when 
designing a micro-benchmark. I hope this time it does the job correctly...

What do you thik? Should I file a RFE first?

Regards, Peter




More information about the core-libs-dev mailing list