[hibernate-issues] [Hibernate-JIRA] Created: (HHH-2990) Bad usage of ClassLoader.loadClass() for Java6 in SerializationHelper$CustomObjectInputStream - deserialization bottleneck for arrays

Tom Eicher (JIRA) noreply at atlassian.com
Tue Dec 4 07:14:56 EST 2007


Bad usage of ClassLoader.loadClass() for Java6 in SerializationHelper$CustomObjectInputStream - deserialization bottleneck for arrays
-------------------------------------------------------------------------------------------------------------------------------------

                 Key: HHH-2990
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2990
             Project: Hibernate3
          Issue Type: Bug
    Affects Versions: 3.2.5
         Environment: Hibernate 3.2.5, Java 6 Sun (any), any platform (tested Linux x64, Mac x64 (J6dp1))
            Reporter: Tom Eicher


Sun has "clarified" (others say modified) the API of "ClassLoader.loadClass()" and no longer allows this to be called for arrays, e.g. String[].
( see: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6500212 and duplicates )
and states that this has always been very unstable to use/do in the first place.
So trying to load an array of something using this method results in ClassNotFoundException.
The correct thing to do is call Class.forName(className,false,myClassLoader); instead of myClassLoader.loadClass(className);

In SerializationHelper$CustomObjectInputStream.resolveClass() we do

			ClassLoader loader = Thread.currentThread().getContextClassLoader();
			try {
				resolvedClass = loader.loadClass(className);
				log.trace("Class resolved through context class loader");
			}
			catch(ClassNotFoundException e) {
				log.trace("Asking super to resolve");
				resolvedClass = super.resolveClass(v);
			}

which results in the deserialization process for a String[] always searching String[] in all the application's jars/wars/etc before really loading it.
The bad thing is, loadClass() is synchronized.

In our case, we have multiple threads loading database rows containing String[]s, which results in one Thread doing

INFO   | jvm 1    | 2007/11/30 16:56:44 |    java.lang.Thread.State: RUNNABLE
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.util.zip.ZipFile.getEntry(Native Method)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.util.zip.ZipFile.getEntry(ZipFile.java:149)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       - locked <0x00002aaab4047c20> (a java.util.jar.JarFile)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.util.jar.JarFile.getEntry(JarFile.java:206)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.util.jar.JarFile.getJarEntry(JarFile.java:189)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:754)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at sun.misc.URLClassPath.getResource(URLClassPath.java:168)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.net.URLClassLoader$1.run(URLClassLoader.java:192)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.security.AccessController.doPrivileged(Native Method)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       - locked <0x00002aaab4025998> (a org.apache.catalina.loader.StandardClassLoader)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       - locked <0x00002aaab4095a68> (a org.apache.catalina.loader.StandardClassLoader)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1346)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1205)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.hibernate.util.SerializationHelper$CustomObjectInputStream.resolveClass(SerializationHelper.java:263)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1624)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:210)

and all other threads doing nothing

INFO   | jvm 1    | 2007/11/30 16:56:44 |    java.lang.Thread.State: BLOCKED (on object monitor)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.lang.ClassLoader.loadClass(ClassLoader.java:295)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       - waiting to lock <0x00002aaab4095a68> (a org.apache.catalina.loader.StandardClassLoader)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1346)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1205)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at org.hibernate.util.SerializationHelper$CustomObjectInputStream.resolveClass(SerializationHelper.java:263)
INFO   | jvm 1    | 2007/11/30 16:56:44 |       at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
(rest of stack trace identical to above)

This can easily be worked around by setting the compatibility property 
   -Dsun.lang.ClassLoader.allowArraySyntax=true
however a) this workaround might not be around for long and b) most people will never find this bottleneck, therefore will not apply the workaround.
For our case, we got a 35% performance increase just be setting this property (and not a single loadClass() or ZipFile.getEntry() in any thread dump any more).

Cheers, Tom.





-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list