Hello,
We have an issue in Hibernate ORM 3.6.1 related with the classloading. It is seen in
weblogic application server when many concurrent threads are trying to execute hibernate
queries.
When a HQL query is executed, first time it is parsed and than cached. Subsequent calls do
not have any issues. If too many threads are doing parse operation, because of the single
threaded nature of classloading (java6) many threads are waiting the thread doing the
parse operation.
An example : "from Device dev where dev.deleted = 0"
When hibernate is executing the query above, it is first parsed. During the parse
operation hibernate is checking the alias name "dev" as a class. A class load
operation is executed. It will not find a class named "dev", but for some reason
it is doing a lookup. The package name of "Device" class like
"com.mycompany.domain" is also looked up as a class by doing class load
operation. If there are many (400+) concurrent threads, doing same hibernate call, they
are stuck in the parsing because of single threaded class loading.
This behavior is causing long warm up time in the application server when there is a burs
t of traffic.
As an improvement, I am planning to add a negative cache for the non existing classes to
prevent going to the class loader again and again.
Here is the modification in ReflectHelper.java: (Changes are in red)
private static Map<String, Boolean> hmNonExistingClasses = new
ConcurrentHashMap<String, Boolean>();
/**
* Perform resolution of a class name.
* <p/>
* Same as {@link #classForName(String, Class)} except that here we delegate to
* {@link Class#forName(String)} if the context classloader lookup is
unsuccessful.
*
* @param name The class name
* @return The class reference.
* @throws ClassNotFoundException From {@link Class#forName(String)}.
*/
public static Class classForName(String name) throws ClassNotFoundException {
if (hmNonExistingClasses.containsKey(name))
throw new ClassNotFoundException(name);
try {
ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
if ( contextClassLoader != null ) {
return contextClassLoader.loadClass(name);
}
}
catch ( Throwable ignore ) {
}
try {
return Class.forName( name );
} catch (ClassNotFoundException cnfe) {
hmNonExistingClasses.put(name, true);
throw cnfe;
}
}
Can you please also let me know if I can make this change in hibernate 3.6.1 (in a new
branc)without making our product open source? My understanding is, I need to make this
change public. I have created a new branch locally in git and want to push the changes to
a new branch named "3.6.1.Final_ALU" in github. Can you please let me know if I
can create the new branch?
Thanks for your help,
Bahadir DANISIK.
Show replies by date