In our web application exists 'Access Bean' classes with some methods on them which perform queries on a DB, these are invoked multiple times per request. Therefore they need to be cached but the original classes cannot be altered as they are from the framework we use, so to work around this, I have created a factory which builds a proxy class to wrap and cache method calls to original existing bean methods. I want to store the proxy class in a ConcurrentHashMap<Class, Class>
(where the key is the original class and the value is the new proxy class) to be quickly retrieved by other threads when needed.
I want it to be fast and with very low contention, so I have to synchronized on the bean class object passed in as a method parameter for double checked locking to get the proxy class from the map or controlling access to the proxy factory if the proxy class is missing.
Map<Class, Class> classProxyMap = ConcurrentHashMap<Class, Class>;
@SuppressWarnings("unchecked")
private static <P extends B> Class<P> getProxyClass(Class<B> beanClass) {
Class<P> proxyClass = classProxyMap.get(beanClass);
if (proxyClass == null) {
synchronized (beanClass) {
proxyClass = classProxyMap.get(beanClass);
if (proxyClass == null) {
proxyClass = proxyFactory.makeProxyClass(beanClass, false);
classProxyMap.put(beanClass, proxyClass);
}
}
}
return (Class<P>) proxyClass;
}
It seems as though this is failing in a QA environment, although I am not entirely sure this (synchronization) is the issue. Therefore I want to know if it is ok to synchronize in this way or should I just synchonize on the map and be done with it.
[EDIT] The Application server is Java 7 so ConcurrentHashMap.computeIfAbsent is not an option