Author: rjung
Date: Thu May 6 19:17:49 2010
New Revision: 941868
URL: http://svn.apache.org/viewvc?rev=941868&view=rev
Log:
BZ48903: Fix deadlock in webapp class loader.
Backport of r927565 and r927877 from trunk.
Already applied to TC 5.5 as r935947.
Modified:
tomcat/tc6.0.x/trunk/STATUS.txt
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java
tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Thu May 6 19:17:49 2010
@@ -142,28 +142,6 @@ PATCHES PROPOSED TO BACKPORT:
kkolinko: We have to mention the new parameter in
jasper-howto.html#Configuration
-* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=48903
- and https://issues.apache.org/bugzilla/show_bug.cgi?id=48694#c8
- Fix deadlock /sync issues in WebappClassLoader. Revert to using
- synchronized(this) as analysis and experience shows anything else will just
- cause problems
- The patch looks huge but it just removes the sync block and sync's the method
- http://svn.apache.org/viewvc?rev=927565&view=rev
- svn diff -x -w -r927564:927565 http://svn.apache.org/repos/asf/tomcat/trunk
- +1: markt, kkolinko, rjung
- -1:
-
- Additional patch:
- Mark ResourceEntry.loadedClass as volatile.
- http://svn.apache.org/viewvc?rev=927877&view=rev
- +1: kkolinko, markt, rjung
- -1:
-
- Note: (kkolinko): Applied to 5.5.x in r935947. The above patches address
- BZ 44041, BZ 48903, BZ 48694. Those three issues are to be marked as
RESOLVED,
- when these patches are applied.
-
-
* Correct SSL session timeout attribute name
http://people.apache.org/~markt/patches/2010-04-07-SslSessionTimeout.patch
+1: markt
Modified:
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java Thu
May 6 19:17:49 2010
@@ -47,7 +47,7 @@ public class ResourceEntry {
/**
* Loaded class.
*/
- public Class loadedClass = null;
+ public volatile Class loadedClass = null;
/**
Modified:
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
Thu May 6 19:17:49 2010
@@ -1432,102 +1432,121 @@ public class WebappClassLoader
*
* @exception ClassNotFoundException if the class was not found
*/
- public Class loadClass(String name, boolean resolve)
+ public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
- synchronized (name.intern()) {
- if (log.isDebugEnabled())
- log.debug("loadClass(" + name + ", " + resolve + ")");
- Class clazz = null;
-
- // Log access to stopped classloader
- if (!started) {
- try {
- throw new IllegalStateException();
- } catch (IllegalStateException e) {
- log.info(sm.getString("webappClassLoader.stopped", name),
e);
- }
+ if (log.isDebugEnabled())
+ log.debug("loadClass(" + name + ", " + resolve + ")");
+ Class clazz = null;
+
+ // Log access to stopped classloader
+ if (!started) {
+ try {
+ throw new IllegalStateException();
+ } catch (IllegalStateException e) {
+ log.info(sm.getString("webappClassLoader.stopped", name), e);
}
-
- // (0) Check our previously loaded local class cache
- clazz = findLoadedClass0(name);
+ }
+
+ // (0) Check our previously loaded local class cache
+ clazz = findLoadedClass0(name);
+ if (clazz != null) {
+ if (log.isDebugEnabled())
+ log.debug(" Returning class from cache");
+ if (resolve)
+ resolveClass(clazz);
+ return (clazz);
+ }
+
+ // (0.1) Check our previously loaded class cache
+ clazz = findLoadedClass(name);
+ if (clazz != null) {
+ if (log.isDebugEnabled())
+ log.debug(" Returning class from cache");
+ if (resolve)
+ resolveClass(clazz);
+ return (clazz);
+ }
+
+ // (0.2) Try loading the class with the system class loader, to prevent
+ // the webapp from overriding J2SE classes
+ try {
+ clazz = system.loadClass(name);
if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
-
- // (0.1) Check our previously loaded class cache
- clazz = findLoadedClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Returning class from cache");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
+ } catch (ClassNotFoundException e) {
+ // Ignore
+ }
+
+ // (0.5) Permission to access this class when using a SecurityManager
+ if (securityManager != null) {
+ int i = name.lastIndexOf('.');
+ if (i >= 0) {
+ try {
+ securityManager.checkPackageAccess(name.substring(0,i));
+ } catch (SecurityException se) {
+ String error = "Security Violation, attempt to use " +
+ "Restricted Class: " + name;
+ log.info(error, se);
+ throw new ClassNotFoundException(error, se);
+ }
}
-
- // (0.2) Try loading the class with the system class loader, to
prevent
- // the webapp from overriding J2SE classes
+ }
+
+ boolean delegateLoad = delegate || filter(name);
+
+ // (1) Delegate to our parent if requested
+ if (delegateLoad) {
+ if (log.isDebugEnabled())
+ log.debug(" Delegating to parent classloader1 " + parent);
+ ClassLoader loader = parent;
+ if (loader == null)
+ loader = system;
try {
- clazz = system.loadClass(name);
+ clazz = loader.loadClass(name);
if (clazz != null) {
+ if (log.isDebugEnabled())
+ log.debug(" Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
- // Ignore
- }
-
- // (0.5) Permission to access this class when using a
SecurityManager
- if (securityManager != null) {
- int i = name.lastIndexOf('.');
- if (i >= 0) {
- try {
-
securityManager.checkPackageAccess(name.substring(0,i));
- } catch (SecurityException se) {
- String error = "Security Violation, attempt to use " +
- "Restricted Class: " + name;
- log.info(error, se);
- throw new ClassNotFoundException(error, se);
- }
- }
+ ;
}
-
- boolean delegateLoad = delegate || filter(name);
-
- // (1) Delegate to our parent if requested
- if (delegateLoad) {
+ }
+
+ // (2) Search local repositories
+ if (log.isDebugEnabled())
+ log.debug(" Searching local repositories");
+ try {
+ clazz = findClass(name);
+ if (clazz != null) {
if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader1 " + parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- try {
- clazz = loader.loadClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from parent");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
- } catch (ClassNotFoundException e) {
- ;
- }
+ log.debug(" Loading class from local repository");
+ if (resolve)
+ resolveClass(clazz);
+ return (clazz);
}
-
- // (2) Search local repositories
+ } catch (ClassNotFoundException e) {
+ ;
+ }
+
+ // (3) Delegate to parent unconditionally
+ if (!delegateLoad) {
if (log.isDebugEnabled())
- log.debug(" Searching local repositories");
+ log.debug(" Delegating to parent classloader at end: " +
parent);
+ ClassLoader loader = parent;
+ if (loader == null)
+ loader = system;
try {
- clazz = findClass(name);
+ clazz = loader.loadClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
- log.debug(" Loading class from local repository");
+ log.debug(" Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
@@ -1535,30 +1554,10 @@ public class WebappClassLoader
} catch (ClassNotFoundException e) {
;
}
-
- // (3) Delegate to parent unconditionally
- if (!delegateLoad) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader at end: " +
parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- try {
- clazz = loader.loadClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from parent");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
- } catch (ClassNotFoundException e) {
- ;
- }
- }
-
- throw new ClassNotFoundException(name);
}
+
+ throw new ClassNotFoundException(name);
+
}
@@ -2544,7 +2543,7 @@ public class WebappClassLoader
if (clazz != null)
return clazz;
- synchronized (name.intern()) {
+ synchronized (this) {
clazz = entry.loadedClass;
if (clazz != null)
return clazz;
Modified: tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java Thu
May 6 19:17:49 2010
@@ -91,7 +91,7 @@ public class JasperLoader extends URLCla
*
* @exception ClassNotFoundException if the class was not found
*/
- public Class loadClass(final String name, boolean resolve)
+ public synchronized Class loadClass(final String name, boolean resolve)
throws ClassNotFoundException {
Class clazz = null;
@@ -169,4 +169,4 @@ public class JasperLoader extends URLCla
public final PermissionCollection getPermissions(CodeSource codeSource) {
return permissionCollection;
}
-}
\ No newline at end of file
+}
Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Thu May 6 19:17:49 2010
@@ -47,6 +47,9 @@
address via the HTTP WWW-Authenticate header when using BASIC or DIGEST
authentication. (markt)
</fix>
+ <fix>
+ <bug>48903</bug>: Fix deadlock in webapp class loader. (rjung)
+ </fix>
<add>
Include context name when reporting memory leaks to aid root cause
identification. (markt)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]