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.




_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Reply via email to