Improved synchronization handling around defining classes since it appears
that we cannot assume that the class loader is locked by the VM.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@540651 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
index 1f32645..70c08e2 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
@@ -84,9 +84,13 @@
protected Class findClass(String name) throws ClassNotFoundException
{
-// TODO: ML - We probably need to do this check closer to defineClass() and
-// protect it with a synchronized block.
- Class clazz = findLoadedClass(name);
+ // Do a quick check here to see if we can short-circuit this
+ // entire process if the class was already loaded.
+ Class clazz = null;
+ synchronized (this)
+ {
+ clazz = findLoadedClass(name);
+ }
// Search for class in module.
if (clazz == null)
@@ -104,49 +108,60 @@
if (bytes != null)
{
- // We need to try to define a Package object for the class
- // before we call defineClass(). Get the package name and
- // see if we have already created the package.
- String pkgName = Util.getClassPackage(name);
- if (pkgName.length() > 0)
+ // Before we actually attempt to define the class, grab
+ // the lock for this class loader and make sure than no
+ // other thread has defined this class in the meantime.
+ synchronized (this)
{
- if (getPackage(pkgName) == null)
+ clazz = findLoadedClass(name);
+
+ if (clazz == null)
{
- Object[] params =
- m_contentLoader.getSearchPolicy()
- .definePackage(pkgName);
- if (params != null)
+ // We need to try to define a Package object for the class
+ // before we call defineClass(). Get the package name and
+ // see if we have already created the package.
+ String pkgName = Util.getClassPackage(name);
+ if (pkgName.length() > 0)
{
- definePackage(
- pkgName,
- (String) params[0],
- (String) params[1],
- (String) params[2],
- (String) params[3],
- (String) params[4],
- (String) params[5],
- null);
+ if (getPackage(pkgName) == null)
+ {
+ Object[] params =
+ m_contentLoader.getSearchPolicy()
+ .definePackage(pkgName);
+ if (params != null)
+ {
+ definePackage(
+ pkgName,
+ (String) params[0],
+ (String) params[1],
+ (String) params[2],
+ (String) params[3],
+ (String) params[4],
+ (String) params[5],
+ null);
+ }
+ else
+ {
+ definePackage(pkgName, null, null,
+ null, null, null, null, null);
+ }
+ }
+ }
+
+ // If we have a security context, then use it to
+ // define the class with it for security purposes,
+ // otherwise define the class without a protection domain.
+ if (m_protectionDomain != null)
+ {
+ clazz = defineClass(name, bytes, 0, bytes.length,
+ m_protectionDomain);
}
else
{
- definePackage(pkgName, null, null,
- null, null, null, null, null);
+ clazz = defineClass(name, bytes, 0, bytes.length);
}
}
}
-
- // If we have a security context, then use it to
- // define the class with it for security purposes,
- // otherwise define the class without a protection domain.
- if (m_protectionDomain != null)
- {
- clazz = defineClass(name, bytes, 0, bytes.length,
- m_protectionDomain);
- }
- else
- {
- clazz = defineClass(name, bytes, 0, bytes.length);
- }
}
}